##// END OF EJS Templates
Fixed that project settings should show locked members (#22034)....
Jean-Philippe Lang -
r15734:514d9bad9efd
parent child
Show More
@@ -1,129 +1,129
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class MembersController < ApplicationController
19 19 model_object Member
20 20 before_action :find_model_object, :except => [:index, :new, :create, :autocomplete]
21 21 before_action :find_project_from_association, :except => [:index, :new, :create, :autocomplete]
22 22 before_action :find_project_by_project_id, :only => [:index, :new, :create, :autocomplete]
23 23 before_action :authorize
24 24 accept_api_auth :index, :show, :create, :update, :destroy
25 25
26 26 require_sudo_mode :create, :update, :destroy
27 27
28 28 def index
29 scope = @project.memberships.active
29 scope = @project.memberships
30 30 @offset, @limit = api_offset_and_limit
31 31 @member_count = scope.count
32 32 @member_pages = Paginator.new @member_count, @limit, params['page']
33 33 @offset ||= @member_pages.offset
34 34 @members = scope.order(:id).limit(@limit).offset(@offset).to_a
35 35
36 36 respond_to do |format|
37 37 format.html { head 406 }
38 38 format.api
39 39 end
40 40 end
41 41
42 42 def show
43 43 respond_to do |format|
44 44 format.html { head 406 }
45 45 format.api
46 46 end
47 47 end
48 48
49 49 def new
50 50 @member = Member.new
51 51 end
52 52
53 53 def create
54 54 members = []
55 55 if params[:membership]
56 56 user_ids = Array.wrap(params[:membership][:user_id] || params[:membership][:user_ids])
57 57 user_ids << nil if user_ids.empty?
58 58 user_ids.each do |user_id|
59 59 member = Member.new(:project => @project, :user_id => user_id)
60 60 member.set_editable_role_ids(params[:membership][:role_ids])
61 61 members << member
62 62 end
63 63 @project.members << members
64 64 end
65 65
66 66 respond_to do |format|
67 67 format.html { redirect_to_settings_in_projects }
68 68 format.js {
69 69 @members = members
70 70 @member = Member.new
71 71 }
72 72 format.api {
73 73 @member = members.first
74 74 if @member.valid?
75 75 render :action => 'show', :status => :created, :location => membership_url(@member)
76 76 else
77 77 render_validation_errors(@member)
78 78 end
79 79 }
80 80 end
81 81 end
82 82
83 83 def update
84 84 if params[:membership]
85 85 @member.set_editable_role_ids(params[:membership][:role_ids])
86 86 end
87 87 saved = @member.save
88 88 respond_to do |format|
89 89 format.html { redirect_to_settings_in_projects }
90 90 format.js
91 91 format.api {
92 92 if saved
93 93 render_api_ok
94 94 else
95 95 render_validation_errors(@member)
96 96 end
97 97 }
98 98 end
99 99 end
100 100
101 101 def destroy
102 102 if @member.deletable?
103 103 @member.destroy
104 104 end
105 105 respond_to do |format|
106 106 format.html { redirect_to_settings_in_projects }
107 107 format.js
108 108 format.api {
109 109 if @member.destroyed?
110 110 render_api_ok
111 111 else
112 112 head :unprocessable_entity
113 113 end
114 114 }
115 115 end
116 116 end
117 117
118 118 def autocomplete
119 119 respond_to do |format|
120 120 format.js
121 121 end
122 122 end
123 123
124 124 private
125 125
126 126 def redirect_to_settings_in_projects
127 127 redirect_to settings_project_path(@project, :tab => 'members')
128 128 end
129 129 end
@@ -1,62 +1,62
1 1 <% roles = Role.find_all_givable
2 members = @project.memberships.active.sorted.to_a %>
2 members = @project.memberships.sorted.to_a %>
3 3
4 4 <p><%= link_to l(:label_member_new), new_project_membership_path(@project), :remote => true, :class => "icon icon-add" %></p>
5 5
6 6 <% if members.any? %>
7 7 <table class="list members">
8 8 <thead>
9 9 <tr>
10 10 <th><%= l(:label_user) %> / <%= l(:label_group) %></th>
11 11 <th><%= l(:label_role_plural) %></th>
12 12 <th style="width:15%"></th>
13 13 <%= call_hook(:view_projects_settings_members_table_header, :project => @project) %>
14 14 </tr>
15 15 </thead>
16 16 <tbody>
17 17 <% members.each do |member| %>
18 18 <% next if member.new_record? %>
19 19 <tr id="member-<%= member.id %>" class="<%= cycle 'odd', 'even' %> member">
20 20 <td class="name icon icon-<%= member.principal.class.name.downcase %>"><%= link_to_user member.principal %></td>
21 21 <td class="roles">
22 22 <span id="member-<%= member.id %>-roles"><%= member.roles.sort.collect(&:to_s).join(', ') %></span>
23 23 <%= form_for(member,
24 24 {:as => :membership, :remote => true,
25 25 :url => membership_path(member),
26 26 :method => :put,
27 27 :html => { :id => "member-#{member.id}-roles-form", :class => 'hol' }}
28 28 ) do |f| %>
29 29 <p>
30 30 <% roles.each do |role| %>
31 31 <label>
32 32 <%= check_box_tag('membership[role_ids][]',
33 33 role.id, member.roles.include?(role),
34 34 :id => nil,
35 35 :disabled => !member.role_editable?(role)) %> <%= role %>
36 36 </label><br />
37 37 <% end %>
38 38 </p>
39 39 <%= hidden_field_tag 'membership[role_ids][]', '', :id => nil %>
40 40 <p>
41 41 <%= submit_tag l(:button_save), :class => "small" %>
42 42 <%= link_to_function(l(:button_cancel),
43 43 "$('#member-#{member.id}-roles').show(); $('#member-#{member.id}-roles-form').hide(); return false;") %>
44 44 </p>
45 45 <% end %>
46 46 </td>
47 47 <td class="buttons">
48 48 <%= link_to_function l(:button_edit),
49 49 "$('#member-#{member.id}-roles').hide(); $('#member-#{member.id}-roles-form').show(); return false;",
50 50 :class => 'icon icon-edit' %>
51 51 <%= delete_link membership_path(member),
52 52 :remote => true,
53 53 :data => (!User.current.admin? && member.include?(User.current) ? {:confirm => l(:text_own_membership_delete_confirmation)} : {}) if member.deletable? %>
54 54 </td>
55 55 <%= call_hook(:view_projects_settings_members_table_row, { :project => @project, :member => member}) %>
56 56 </tr>
57 57 <% end; reset_cycle %>
58 58 </tbody>
59 59 </table>
60 60 <% else %>
61 61 <p class="nodata"><%= l(:label_no_data) %></p>
62 62 <% end %>
@@ -1,197 +1,215
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class MembersControllerTest < Redmine::ControllerTest
21 21 fixtures :projects, :members, :member_roles, :roles, :users
22 22
23 23 def setup
24 24 User.current = nil
25 25 @request.session[:user_id] = 2
26 26 end
27 27
28 28 def test_new
29 29 get :new, :project_id => 1
30 30 assert_response :success
31 31 end
32 32
33 33 def test_new_should_propose_managed_roles_only
34 34 role = Role.find(1)
35 35 role.update! :all_roles_managed => false
36 36 role.managed_roles = Role.where(:id => [2, 3]).to_a
37 37
38 38 get :new, :project_id => 1
39 39 assert_response :success
40 40 assert_select 'div.roles-selection' do
41 41 assert_select 'label', :text => 'Manager', :count => 0
42 42 assert_select 'label', :text => 'Developer'
43 43 assert_select 'label', :text => 'Reporter'
44 44 end
45 45 end
46 46
47 47 def test_xhr_new
48 48 xhr :get, :new, :project_id => 1
49 49 assert_response :success
50 50 assert_equal 'text/javascript', response.content_type
51 51 end
52 52
53 53 def test_create
54 54 assert_difference 'Member.count' do
55 55 post :create, :project_id => 1, :membership => {:role_ids => [1], :user_id => 7}
56 56 end
57 57 assert_redirected_to '/projects/ecookbook/settings/members'
58 58 assert User.find(7).member_of?(Project.find(1))
59 59 end
60 60
61 61 def test_create_multiple
62 62 assert_difference 'Member.count', 3 do
63 63 post :create, :project_id => 1, :membership => {:role_ids => [1], :user_ids => [7, 8, 9]}
64 64 end
65 65 assert_redirected_to '/projects/ecookbook/settings/members'
66 66 assert User.find(7).member_of?(Project.find(1))
67 67 end
68 68
69 69 def test_create_should_ignore_unmanaged_roles
70 70 role = Role.find(1)
71 71 role.update! :all_roles_managed => false
72 72 role.managed_roles = Role.where(:id => [2, 3]).to_a
73 73
74 74 assert_difference 'Member.count' do
75 75 post :create, :project_id => 1, :membership => {:role_ids => [1, 2], :user_id => 7}
76 76 end
77 77 member = Member.order(:id => :desc).first
78 78 assert_equal [2], member.role_ids
79 79 end
80 80
81 81 def test_create_should_be_allowed_for_admin_without_role
82 82 User.find(1).members.delete_all
83 83 @request.session[:user_id] = 1
84 84
85 85 assert_difference 'Member.count' do
86 86 post :create, :project_id => 1, :membership => {:role_ids => [1, 2], :user_id => 7}
87 87 end
88 88 member = Member.order(:id => :desc).first
89 89 assert_equal [1, 2], member.role_ids
90 90 end
91 91
92 92 def test_xhr_create
93 93 assert_difference 'Member.count', 3 do
94 94 xhr :post, :create, :project_id => 1, :membership => {:role_ids => [1], :user_ids => [7, 8, 9]}
95 95 assert_response :success
96 96 assert_equal 'text/javascript', response.content_type
97 97 end
98 98 assert User.find(7).member_of?(Project.find(1))
99 99 assert User.find(8).member_of?(Project.find(1))
100 100 assert User.find(9).member_of?(Project.find(1))
101 101 assert_include 'tab-content-members', response.body
102 102 end
103 103
104 104 def test_xhr_create_with_failure
105 105 assert_no_difference 'Member.count' do
106 106 xhr :post, :create, :project_id => 1, :membership => {:role_ids => [], :user_ids => [7, 8, 9]}
107 107 assert_response :success
108 108 assert_equal 'text/javascript', response.content_type
109 109 end
110 110 assert_match /alert/, response.body, "Alert message not sent"
111 111 end
112 112
113 113 def test_update
114 114 assert_no_difference 'Member.count' do
115 115 put :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
116 116 end
117 117 assert_redirected_to '/projects/ecookbook/settings/members'
118 118 end
119 119
120 def test_update_locked_member_should_be_allowed
121 User.find(3).lock!
122
123 put :update, :id => 2, :membership => {:role_ids => [1]}
124 assert_response 302
125 member = Member.find(2)
126 assert member.user.locked?
127 assert_equal [1], member.role_ids
128 end
129
120 130 def test_update_should_not_add_unmanaged_roles
121 131 role = Role.find(1)
122 132 role.update! :all_roles_managed => false
123 133 role.managed_roles = Role.where(:id => [2, 3]).to_a
124 134 member = Member.create!(:user => User.find(9), :role_ids => [3], :project_id => 1)
125 135
126 136 put :update, :id => member.id, :membership => {:role_ids => [1, 2, 3]}
127 137 assert_equal [2, 3], member.reload.role_ids.sort
128 138 end
129 139
130 140 def test_update_should_not_remove_unmanaged_roles
131 141 role = Role.find(1)
132 142 role.update! :all_roles_managed => false
133 143 role.managed_roles = Role.where(:id => [2, 3]).to_a
134 144 member = Member.create!(:user => User.find(9), :role_ids => [1, 3], :project_id => 1)
135 145
136 146 put :update, :id => member.id, :membership => {:role_ids => [2]}
137 147 assert_equal [1, 2], member.reload.role_ids.sort
138 148 end
139 149
140 150 def test_xhr_update
141 151 assert_no_difference 'Member.count' do
142 152 xhr :put, :update, :id => 2, :membership => {:role_ids => [1], :user_id => 3}
143 153 assert_response :success
144 154 assert_equal 'text/javascript', response.content_type
145 155 end
146 156 member = Member.find(2)
147 157 assert_equal [1], member.role_ids
148 158 assert_equal 3, member.user_id
149 159 assert_include 'tab-content-members', response.body
150 160 end
151 161
152 162 def test_destroy
153 163 assert_difference 'Member.count', -1 do
154 164 delete :destroy, :id => 2
155 165 end
156 166 assert_redirected_to '/projects/ecookbook/settings/members'
157 167 assert !User.find(3).member_of?(Project.find(1))
158 168 end
159 169
170 def test_destroy_locked_member_should_be_allowed
171 assert User.find(3).lock!
172
173 assert_difference 'Member.count', -1 do
174 delete :destroy, :id => 2
175 end
176 end
177
160 178 def test_destroy_should_fail_with_unmanaged_roles
161 179 role = Role.find(1)
162 180 role.update! :all_roles_managed => false
163 181 role.managed_roles = Role.where(:id => [2, 3]).to_a
164 182 member = Member.create!(:user => User.find(9), :role_ids => [1, 3], :project_id => 1)
165 183
166 184 assert_no_difference 'Member.count' do
167 185 delete :destroy, :id => member.id
168 186 end
169 187 end
170 188
171 189 def test_destroy_should_succeed_with_managed_roles_only
172 190 role = Role.find(1)
173 191 role.update! :all_roles_managed => false
174 192 role.managed_roles = Role.where(:id => [2, 3]).to_a
175 193 member = Member.create!(:user => User.find(9), :role_ids => [3], :project_id => 1)
176 194
177 195 assert_difference 'Member.count', -1 do
178 196 delete :destroy, :id => member.id
179 197 end
180 198 end
181 199
182 200 def test_xhr_destroy
183 201 assert_difference 'Member.count', -1 do
184 202 xhr :delete, :destroy, :id => 2
185 203 assert_response :success
186 204 assert_equal 'text/javascript', response.content_type
187 205 end
188 206 assert_nil Member.find_by_id(2)
189 207 assert_include 'tab-content-members', response.body
190 208 end
191 209
192 210 def test_autocomplete
193 211 xhr :get, :autocomplete, :project_id => 1, :q => 'mis', :format => 'js'
194 212 assert_response :success
195 213 assert_include 'User Misc', response.body
196 214 end
197 215 end
@@ -1,755 +1,767
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class ProjectsControllerTest < Redmine::ControllerTest
21 21 fixtures :projects, :versions, :users, :email_addresses, :roles, :members,
22 22 :member_roles, :issues, :journals, :journal_details,
23 23 :trackers, :projects_trackers, :issue_statuses,
24 24 :enabled_modules, :enumerations, :boards, :messages,
25 25 :attachments, :custom_fields, :custom_values, :time_entries,
26 26 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
27 27
28 28 def setup
29 29 @request.session[:user_id] = nil
30 30 Setting.default_language = 'en'
31 31 end
32 32
33 33 def test_index_by_anonymous_should_not_show_private_projects
34 34 get :index
35 35 assert_response :success
36 36
37 37 assert_select 'ul' do
38 38 assert_select 'li' do
39 39 assert_select 'a', :text => 'eCookbook'
40 40 assert_select 'ul' do
41 41 assert_select 'a', :text => 'Child of private child'
42 42 end
43 43 end
44 44 end
45 45 assert_select 'a', :text => /Private child of eCookbook/, :count => 0
46 46 end
47 47
48 48 def test_index_atom
49 49 get :index, :format => 'atom'
50 50 assert_response :success
51 51 assert_select 'feed>title', :text => 'Redmine: Latest projects'
52 52 assert_select 'feed>entry', :count => Project.visible(User.current).count
53 53 end
54 54
55 55 def test_index_js
56 56 xhr :get, :index, :format => 'js', :q => 'coo'
57 57 assert_response :success
58 58 assert_equal 'text/javascript', response.content_type
59 59 end
60 60
61 61 test "#index by non-admin user with view_time_entries permission should show overall spent time link" do
62 62 @request.session[:user_id] = 3
63 63 get :index
64 64 assert_select 'a[href=?]', '/time_entries'
65 65 end
66 66
67 67 test "#index by non-admin user without view_time_entries permission should not show overall spent time link" do
68 68 Role.find(2).remove_permission! :view_time_entries
69 69 Role.non_member.remove_permission! :view_time_entries
70 70 Role.anonymous.remove_permission! :view_time_entries
71 71 @request.session[:user_id] = 3
72 72
73 73 get :index
74 74 assert_select 'a[href=?]', '/time_entries', 0
75 75 end
76 76
77 77 test "#index by non-admin user with permission should show add project link" do
78 78 Role.find(1).add_permission! :add_project
79 79 @request.session[:user_id] = 2
80 80
81 81 get :index
82 82 assert_select 'a[href=?]', '/projects/new'
83 83 end
84 84
85 85 test "#new by admin user should accept get" do
86 86 @request.session[:user_id] = 1
87 87
88 88 get :new
89 89 assert_response :success
90 90 assert_select 'input[name=?]', 'project[name]'
91 91 assert_select 'select[name=?]', 'project[parent_id]'
92 92 end
93 93
94 94 test "#new by non-admin user with add_project permission should accept get" do
95 95 Role.non_member.add_permission! :add_project
96 96 @request.session[:user_id] = 9
97 97
98 98 get :new
99 99 assert_response :success
100 100 assert_select 'input[name=?]', 'project[name]'
101 101 assert_select 'select[name=?]', 'project[parent_id]', 0
102 102 end
103 103
104 104 test "#new by non-admin user with add_subprojects permission should accept get" do
105 105 Role.find(1).remove_permission! :add_project
106 106 Role.find(1).add_permission! :add_subprojects
107 107 @request.session[:user_id] = 2
108 108
109 109 get :new, :parent_id => 'ecookbook'
110 110 assert_response :success
111 111
112 112 assert_select 'select[name=?]', 'project[parent_id]' do
113 113 # parent project selected
114 114 assert_select 'option[value="1"][selected=selected]'
115 115 # no empty value
116 116 assert_select 'option[value=""]', 0
117 117 end
118 118 end
119 119
120 120 def test_new_by_non_admin_should_display_modules_if_default_role_is_allowed_to_select_modules
121 121 Role.non_member.add_permission!(:add_project)
122 122 default_role = Role.generate!(:permissions => [:view_issues])
123 123 user = User.generate!
124 124 @request.session[:user_id] = user.id
125 125
126 126 with_settings :new_project_user_role_id => default_role.id.to_s do
127 127 get :new
128 128 assert_select 'input[name=?]', 'project[enabled_module_names][]', 0
129 129
130 130 default_role.add_permission!(:select_project_modules)
131 131 get :new
132 132 assert_select 'input[name=?]', 'project[enabled_module_names][]'
133 133 end
134 134 end
135 135
136 136 def test_new_should_not_display_invalid_search_link
137 137 @request.session[:user_id] = 1
138 138
139 139 get :new
140 140 assert_response :success
141 141 assert_select '#quick-search form[action=?]', '/search'
142 142 assert_select '#quick-search a[href=?]', '/search'
143 143 end
144 144
145 145 test "#create by admin user should create a new project" do
146 146 @request.session[:user_id] = 1
147 147
148 148 post :create,
149 149 :project => {
150 150 :name => "blog",
151 151 :description => "weblog",
152 152 :homepage => 'http://weblog',
153 153 :identifier => "blog",
154 154 :is_public => 1,
155 155 :custom_field_values => { '3' => 'Beta' },
156 156 :tracker_ids => ['1', '3'],
157 157 # an issue custom field that is not for all project
158 158 :issue_custom_field_ids => ['9'],
159 159 :enabled_module_names => ['issue_tracking', 'news', 'repository']
160 160 }
161 161 assert_redirected_to '/projects/blog/settings'
162 162
163 163 project = Project.find_by_name('blog')
164 164 assert_kind_of Project, project
165 165 assert project.active?
166 166 assert_equal 'weblog', project.description
167 167 assert_equal 'http://weblog', project.homepage
168 168 assert_equal true, project.is_public?
169 169 assert_nil project.parent
170 170 assert_equal 'Beta', project.custom_value_for(3).value
171 171 assert_equal [1, 3], project.trackers.map(&:id).sort
172 172 assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
173 173 assert project.issue_custom_fields.include?(IssueCustomField.find(9))
174 174 end
175 175
176 176 test "#create by admin user should create a new subproject" do
177 177 @request.session[:user_id] = 1
178 178
179 179 assert_difference 'Project.count' do
180 180 post :create, :project => { :name => "blog",
181 181 :description => "weblog",
182 182 :identifier => "blog",
183 183 :is_public => 1,
184 184 :custom_field_values => { '3' => 'Beta' },
185 185 :parent_id => 1
186 186 }
187 187 assert_redirected_to '/projects/blog/settings'
188 188 end
189 189
190 190 project = Project.find_by_name('blog')
191 191 assert_kind_of Project, project
192 192 assert_equal Project.find(1), project.parent
193 193 end
194 194
195 195 test "#create by admin user should continue" do
196 196 @request.session[:user_id] = 1
197 197
198 198 assert_difference 'Project.count' do
199 199 post :create, :project => {:name => "blog", :identifier => "blog"}, :continue => 'Create and continue'
200 200 end
201 201 assert_redirected_to '/projects/new'
202 202 end
203 203
204 204 test "#create by non-admin user with add_project permission should create a new project" do
205 205 Role.non_member.add_permission! :add_project
206 206 @request.session[:user_id] = 9
207 207
208 208 post :create, :project => { :name => "blog",
209 209 :description => "weblog",
210 210 :identifier => "blog",
211 211 :is_public => 1,
212 212 :custom_field_values => { '3' => 'Beta' },
213 213 :tracker_ids => ['1', '3'],
214 214 :enabled_module_names => ['issue_tracking', 'news', 'repository']
215 215 }
216 216
217 217 assert_redirected_to '/projects/blog/settings'
218 218
219 219 project = Project.find_by_name('blog')
220 220 assert_kind_of Project, project
221 221 assert_equal 'weblog', project.description
222 222 assert_equal true, project.is_public?
223 223 assert_equal [1, 3], project.trackers.map(&:id).sort
224 224 assert_equal ['issue_tracking', 'news', 'repository'], project.enabled_module_names.sort
225 225
226 226 # User should be added as a project member
227 227 assert User.find(9).member_of?(project)
228 228 assert_equal 1, project.members.size
229 229 end
230 230
231 231 test "#create by non-admin user with add_project permission should fail with parent_id" do
232 232 Role.non_member.add_permission! :add_project
233 233 User.find(9).update! :language => 'en'
234 234 @request.session[:user_id] = 9
235 235
236 236 assert_no_difference 'Project.count' do
237 237 post :create, :project => { :name => "blog",
238 238 :description => "weblog",
239 239 :identifier => "blog",
240 240 :is_public => 1,
241 241 :custom_field_values => { '3' => 'Beta' },
242 242 :parent_id => 1
243 243 }
244 244 end
245 245 assert_response :success
246 246 assert_select_error /Subproject of is invalid/
247 247 end
248 248
249 249 test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
250 250 Role.find(1).remove_permission! :add_project
251 251 Role.find(1).add_permission! :add_subprojects
252 252 @request.session[:user_id] = 2
253 253
254 254 post :create, :project => { :name => "blog",
255 255 :description => "weblog",
256 256 :identifier => "blog",
257 257 :is_public => 1,
258 258 :custom_field_values => { '3' => 'Beta' },
259 259 :parent_id => 1
260 260 }
261 261 assert_redirected_to '/projects/blog/settings'
262 262 project = Project.find_by_name('blog')
263 263 assert_equal 1, project.parent_id
264 264 end
265 265
266 266 test "#create by non-admin user with add_subprojects permission should fail without parent_id" do
267 267 Role.find(1).remove_permission! :add_project
268 268 Role.find(1).add_permission! :add_subprojects
269 269 @request.session[:user_id] = 2
270 270
271 271 assert_no_difference 'Project.count' do
272 272 post :create, :project => { :name => "blog",
273 273 :description => "weblog",
274 274 :identifier => "blog",
275 275 :is_public => 1,
276 276 :custom_field_values => { '3' => 'Beta' }
277 277 }
278 278 end
279 279 assert_response :success
280 280 assert_select_error /Subproject of is invalid/
281 281 end
282 282
283 283 test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
284 284 Role.find(1).remove_permission! :add_project
285 285 Role.find(1).add_permission! :add_subprojects
286 286 @request.session[:user_id] = 2
287 287
288 288 assert !User.find(2).member_of?(Project.find(6))
289 289 assert_no_difference 'Project.count' do
290 290 post :create, :project => { :name => "blog",
291 291 :description => "weblog",
292 292 :identifier => "blog",
293 293 :is_public => 1,
294 294 :custom_field_values => { '3' => 'Beta' },
295 295 :parent_id => 6
296 296 }
297 297 end
298 298 assert_response :success
299 299 assert_select_error /Subproject of is invalid/
300 300 end
301 301
302 302 def test_create_by_non_admin_should_accept_modules_if_default_role_is_allowed_to_select_modules
303 303 Role.non_member.add_permission!(:add_project)
304 304 default_role = Role.generate!(:permissions => [:view_issues, :add_project])
305 305 user = User.generate!
306 306 @request.session[:user_id] = user.id
307 307
308 308 with_settings :new_project_user_role_id => default_role.id.to_s, :default_projects_modules => %w(news files) do
309 309 project = new_record(Project) do
310 310 post :create, :project => {
311 311 :name => "blog1",
312 312 :identifier => "blog1",
313 313 :enabled_module_names => ["issue_tracking", "repository"]
314 314 }
315 315 end
316 316 assert_equal %w(files news), project.enabled_module_names.sort
317 317
318 318 default_role.add_permission!(:select_project_modules)
319 319 project = new_record(Project) do
320 320 post :create, :project => {
321 321 :name => "blog2",
322 322 :identifier => "blog2",
323 323 :enabled_module_names => ["issue_tracking", "repository"]
324 324 }
325 325 end
326 326 assert_equal %w(issue_tracking repository), project.enabled_module_names.sort
327 327 end
328 328 end
329 329
330 330 def test_create_subproject_with_inherit_members_should_inherit_members
331 331 Role.find_by_name('Manager').add_permission! :add_subprojects
332 332 parent = Project.find(1)
333 333 @request.session[:user_id] = 2
334 334
335 335 assert_difference 'Project.count' do
336 336 post :create, :project => {
337 337 :name => 'inherited', :identifier => 'inherited', :parent_id => parent.id, :inherit_members => '1'
338 338 }
339 339 assert_response 302
340 340 end
341 341
342 342 project = Project.order('id desc').first
343 343 assert_equal 'inherited', project.name
344 344 assert_equal parent, project.parent
345 345 assert project.memberships.count > 0
346 346 assert_equal parent.memberships.count, project.memberships.count
347 347 end
348 348
349 349 def test_create_should_preserve_modules_on_validation_failure
350 350 with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
351 351 @request.session[:user_id] = 1
352 352 assert_no_difference 'Project.count' do
353 353 post :create, :project => {
354 354 :name => "blog",
355 355 :identifier => "",
356 356 :enabled_module_names => %w(issue_tracking news)
357 357 }
358 358 end
359 359 assert_response :success
360 360 %w(issue_tracking news).each do |mod|
361 361 assert_select 'input[name=?][value=?][checked=checked]', 'project[enabled_module_names][]', mod
362 362 end
363 363 assert_select 'input[name=?][checked=checked]', 'project[enabled_module_names][]', :count => 2
364 364 end
365 365 end
366 366
367 367 def test_show_by_id
368 368 get :show, :id => 1
369 369 assert_response :success
370 370 assert_select '#header h1', :text => "eCookbook"
371 371 end
372 372
373 373 def test_show_by_identifier
374 374 get :show, :id => 'ecookbook'
375 375 assert_response :success
376 376 assert_select '#header h1', :text => "eCookbook"
377 377 end
378 378
379 379 def test_show_should_not_display_empty_sidebar
380 380 p = Project.find(1)
381 381 p.enabled_module_names = []
382 382 p.save!
383 383
384 384 get :show, :id => 'ecookbook'
385 385 assert_response :success
386 386 assert_select '#main.nosidebar'
387 387 end
388 388
389 389 def test_show_should_display_visible_custom_fields
390 390 ProjectCustomField.find_by_name('Development status').update_attribute :visible, true
391 391 get :show, :id => 'ecookbook'
392 392 assert_response :success
393 393
394 394 assert_select 'li', :text => /Development status/
395 395 end
396 396
397 397 def test_show_should_not_display_hidden_custom_fields
398 398 ProjectCustomField.find_by_name('Development status').update_attribute :visible, false
399 399 get :show, :id => 'ecookbook'
400 400 assert_response :success
401 401
402 402 assert_select 'li', :text => /Development status/, :count => 0
403 403 end
404 404
405 405 def test_show_should_not_display_blank_custom_fields_with_multiple_values
406 406 f1 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Foo Bar), :multiple => true
407 407 f2 = ProjectCustomField.generate! :field_format => 'list', :possible_values => %w(Baz Qux), :multiple => true
408 408 project = Project.generate!(:custom_field_values => {f2.id.to_s => %w(Qux)})
409 409
410 410 get :show, :id => project.id
411 411 assert_response :success
412 412
413 413 assert_select 'li', :text => /#{f1.name}/, :count => 0
414 414 assert_select 'li', :text => /#{f2.name}/
415 415 end
416 416
417 417 def test_show_should_not_display_blank_text_custom_fields
418 418 f1 = ProjectCustomField.generate! :field_format => 'text'
419 419
420 420 get :show, :id => 1
421 421 assert_response :success
422 422
423 423 assert_select 'li', :text => /#{f1.name}/, :count => 0
424 424 end
425 425
426 426 def test_show_should_not_fail_when_custom_values_are_nil
427 427 project = Project.find_by_identifier('ecookbook')
428 428 project.custom_values.first.update_attribute(:value, nil)
429 429 get :show, :id => 'ecookbook'
430 430 assert_response :success
431 431 end
432 432
433 433 def show_archived_project_should_be_denied
434 434 project = Project.find_by_identifier('ecookbook')
435 435 project.archive!
436 436
437 437 get :show, :id => 'ecookbook'
438 438 assert_response 403
439 439 assert_select 'p', :text => /archived/
440 440 assert_not_include project.name, response.body
441 441 end
442 442
443 443 def test_show_should_not_show_private_subprojects_that_are_not_visible
444 444 get :show, :id => 'ecookbook'
445 445 assert_response :success
446 446 assert_select 'a', :text => /Private child/, :count => 0
447 447 end
448 448
449 449 def test_show_should_show_private_subprojects_that_are_visible
450 450 @request.session[:user_id] = 2 # manager who is a member of the private subproject
451 451 get :show, :id => 'ecookbook'
452 452 assert_response :success
453 453 assert_select 'a', :text => /Private child/
454 454 end
455 455
456 456 def test_settings
457 457 @request.session[:user_id] = 2 # manager
458 458 get :settings, :id => 1
459 459 assert_response :success
460 460
461 461 assert_select 'input[name=?]', 'project[name]'
462 462 end
463 463
464 464 def test_settings_of_subproject
465 465 @request.session[:user_id] = 2
466 466 get :settings, :id => 'private-child'
467 467 assert_response :success
468 468
469 469 assert_select 'input[type=checkbox][name=?]', 'project[inherit_members]'
470 470 end
471 471
472 472 def test_settings_should_be_denied_for_member_on_closed_project
473 473 Project.find(1).close
474 474 @request.session[:user_id] = 2 # manager
475 475
476 476 get :settings, :id => 1
477 477 assert_response 403
478 478 end
479 479
480 480 def test_settings_should_be_denied_for_anonymous_on_closed_project
481 481 Project.find(1).close
482 482
483 483 get :settings, :id => 1
484 484 assert_response 302
485 485 end
486 486
487 487 def test_setting_with_wiki_module_and_no_wiki
488 488 Project.find(1).wiki.destroy
489 489 Role.find(1).add_permission! :manage_wiki
490 490 @request.session[:user_id] = 2
491 491
492 492 get :settings, :id => 1
493 493 assert_response :success
494 494
495 495 assert_select 'form[action=?]', '/projects/ecookbook/wiki' do
496 496 assert_select 'input[name=?]', 'wiki[start_page]'
497 497 end
498 498 end
499 499
500 500 def test_settings_should_accept_version_status_filter
501 501 @request.session[:user_id] = 2
502 502
503 503 get :settings, :id => 'ecookbook', :tab => 'versions', :version_status => 'locked'
504 504 assert_response :success
505 505
506 506 assert_select 'select[name=version_status]' do
507 507 assert_select 'option[value=locked][selected=selected]'
508 508 end
509 509 assert_select 'table.versions tbody' do
510 510 assert_select 'tr', 1
511 511 assert_select 'td.name', :text => '1.0'
512 512 end
513 513 assert_select 'a#tab-versions[href=?]', '/projects/ecookbook/settings/versions?version_status=locked'
514 514 end
515 515
516 516 def test_settings_should_accept_version_name_filter
517 517 @request.session[:user_id] = 2
518 518
519 519 get :settings, :id => 'ecookbook', :tab => 'versions', :version_status => '', :version_name => '.1'
520 520 assert_response :success
521 521
522 522 assert_select 'input[name=version_name][value=?]', '.1'
523 523 assert_select 'table.versions tbody' do
524 524 assert_select 'tr', 1
525 525 assert_select 'td.name', :text => '0.1'
526 526 end
527 527 assert_select 'a#tab-versions[href=?]', '/projects/ecookbook/settings/versions?version_name=.1&version_status='
528 528 end
529 529
530 def test_settings_should_show_locked_members
531 user = User.generate!
532 member = User.add_to_project(user, Project.find(1))
533 user.lock!
534 assert user.reload.locked?
535 @request.session[:user_id] = 2
536
537 get :settings, :id => 'ecookbook', :tab => 'members'
538 assert_response :success
539 assert_select "tr#member-#{member.id}"
540 end
541
530 542 def test_update
531 543 @request.session[:user_id] = 2 # manager
532 544 post :update, :id => 1, :project => {:name => 'Test changed name',
533 545 :issue_custom_field_ids => ['']}
534 546 assert_redirected_to '/projects/ecookbook/settings'
535 547 project = Project.find(1)
536 548 assert_equal 'Test changed name', project.name
537 549 end
538 550
539 551 def test_update_with_failure
540 552 @request.session[:user_id] = 2 # manager
541 553 post :update, :id => 1, :project => {:name => ''}
542 554 assert_response :success
543 555 assert_select_error /name cannot be blank/i
544 556 end
545 557
546 558 def test_update_should_be_denied_for_member_on_closed_project
547 559 Project.find(1).close
548 560 @request.session[:user_id] = 2 # manager
549 561
550 562 post :update, :id => 1, :project => {:name => 'Closed'}
551 563 assert_response 403
552 564 assert_equal 'eCookbook', Project.find(1).name
553 565 end
554 566
555 567 def test_update_should_be_denied_for_anonymous_on_closed_project
556 568 Project.find(1).close
557 569
558 570 post :update, :id => 1, :project => {:name => 'Closed'}
559 571 assert_response 302
560 572 assert_equal 'eCookbook', Project.find(1).name
561 573 end
562 574
563 575 def test_update_child_project_without_parent_permission_should_not_show_validation_error
564 576 child = Project.generate_with_parent!
565 577 user = User.generate!
566 578 User.add_to_project(user, child, Role.generate!(:permissions => [:edit_project]))
567 579 @request.session[:user_id] = user.id
568 580
569 581 post :update, :id => child.id, :project => {:name => 'Updated'}
570 582 assert_response 302
571 583 assert_match /Successful update/, flash[:notice]
572 584 end
573 585
574 586 def test_modules
575 587 @request.session[:user_id] = 2
576 588 Project.find(1).enabled_module_names = ['issue_tracking', 'news']
577 589
578 590 post :modules, :id => 1, :enabled_module_names => ['issue_tracking', 'repository', 'documents']
579 591 assert_redirected_to '/projects/ecookbook/settings/modules'
580 592 assert_equal ['documents', 'issue_tracking', 'repository'], Project.find(1).enabled_module_names.sort
581 593 end
582 594
583 595 def test_destroy_leaf_project_without_confirmation_should_show_confirmation
584 596 @request.session[:user_id] = 1 # admin
585 597
586 598 assert_no_difference 'Project.count' do
587 599 delete :destroy, :id => 2
588 600 assert_response :success
589 601 end
590 602 assert_select '.warning', :text => /Are you sure you want to delete this project/
591 603 end
592 604
593 605 def test_destroy_without_confirmation_should_show_confirmation_with_subprojects
594 606 @request.session[:user_id] = 1 # admin
595 607
596 608 assert_no_difference 'Project.count' do
597 609 delete :destroy, :id => 1
598 610 assert_response :success
599 611 end
600 612 assert_select 'strong',
601 613 :text => ['Private child of eCookbook',
602 614 'Child of private child, eCookbook Subproject 1',
603 615 'eCookbook Subproject 2'].join(', ')
604 616 end
605 617
606 618 def test_destroy_with_confirmation_should_destroy_the_project_and_subprojects
607 619 @request.session[:user_id] = 1 # admin
608 620
609 621 assert_difference 'Project.count', -5 do
610 622 delete :destroy, :id => 1, :confirm => 1
611 623 assert_redirected_to '/admin/projects'
612 624 end
613 625 assert_nil Project.find_by_id(1)
614 626 end
615 627
616 628 def test_archive
617 629 @request.session[:user_id] = 1 # admin
618 630 post :archive, :id => 1
619 631 assert_redirected_to '/admin/projects'
620 632 assert !Project.find(1).active?
621 633 end
622 634
623 635 def test_archive_with_failure
624 636 @request.session[:user_id] = 1
625 637 Project.any_instance.stubs(:archive).returns(false)
626 638 post :archive, :id => 1
627 639 assert_redirected_to '/admin/projects'
628 640 assert_match /project cannot be archived/i, flash[:error]
629 641 end
630 642
631 643 def test_unarchive
632 644 @request.session[:user_id] = 1 # admin
633 645 Project.find(1).archive
634 646 post :unarchive, :id => 1
635 647 assert_redirected_to '/admin/projects'
636 648 assert Project.find(1).active?
637 649 end
638 650
639 651 def test_close
640 652 @request.session[:user_id] = 2
641 653 post :close, :id => 1
642 654 assert_redirected_to '/projects/ecookbook'
643 655 assert_equal Project::STATUS_CLOSED, Project.find(1).status
644 656 end
645 657
646 658 def test_reopen
647 659 Project.find(1).close
648 660 @request.session[:user_id] = 2
649 661 post :reopen, :id => 1
650 662 assert_redirected_to '/projects/ecookbook'
651 663 assert Project.find(1).active?
652 664 end
653 665
654 666 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
655 667 CustomField.delete_all
656 668 parent = nil
657 669 6.times do |i|
658 670 p = Project.generate_with_parent!(parent)
659 671 get :show, :id => p
660 672 assert_select '#header h1' do
661 673 assert_select 'a', :count => [i, 3].min
662 674 end
663 675
664 676 parent = p
665 677 end
666 678 end
667 679
668 680 def test_get_copy
669 681 @request.session[:user_id] = 1 # admin
670 682 orig = Project.find(1)
671 683
672 684 get :copy, :id => orig.id
673 685 assert_response :success
674 686
675 687 assert_select 'textarea[name=?]', 'project[description]', :text => orig.description
676 688 assert_select 'input[name=?][value=?]', 'project[enabled_module_names][]', 'issue_tracking', 1
677 689 end
678 690
679 691 def test_get_copy_with_invalid_source_should_respond_with_404
680 692 @request.session[:user_id] = 1
681 693 get :copy, :id => 99
682 694 assert_response 404
683 695 end
684 696
685 697 def test_get_copy_should_preselect_custom_fields
686 698 field1 = IssueCustomField.generate!(:is_for_all => false)
687 699 field2 = IssueCustomField.generate!(:is_for_all => false)
688 700 source = Project.generate!(:issue_custom_fields => [field1])
689 701 @request.session[:user_id] = 1
690 702
691 703 get :copy, :id => source.id
692 704 assert_response :success
693 705 assert_select 'fieldset#project_issue_custom_fields' do
694 706 assert_select 'input[type=checkbox][value=?][checked=checked]', field1.id.to_s
695 707 assert_select 'input[type=checkbox][value=?]:not([checked])', field2.id.to_s
696 708 end
697 709 end
698 710
699 711 def test_post_copy_should_copy_requested_items
700 712 @request.session[:user_id] = 1 # admin
701 713 CustomField.delete_all
702 714
703 715 assert_difference 'Project.count' do
704 716 post :copy, :id => 1,
705 717 :project => {
706 718 :name => 'Copy',
707 719 :identifier => 'unique-copy',
708 720 :tracker_ids => ['1', '2', '3', ''],
709 721 :enabled_module_names => %w(issue_tracking time_tracking)
710 722 },
711 723 :only => %w(issues versions)
712 724 end
713 725 project = Project.find('unique-copy')
714 726 source = Project.find(1)
715 727 assert_equal %w(issue_tracking time_tracking), project.enabled_module_names.sort
716 728
717 729 assert_equal source.versions.count, project.versions.count, "All versions were not copied"
718 730 assert_equal source.issues.count, project.issues.count, "All issues were not copied"
719 731 assert_equal 0, project.members.count
720 732 end
721 733
722 734 def test_post_copy_should_redirect_to_settings_when_successful
723 735 @request.session[:user_id] = 1 # admin
724 736 post :copy, :id => 1, :project => {:name => 'Copy', :identifier => 'unique-copy'}
725 737 assert_response :redirect
726 738 assert_redirected_to :controller => 'projects', :action => 'settings', :id => 'unique-copy'
727 739 end
728 740
729 741 def test_post_copy_with_failure
730 742 @request.session[:user_id] = 1
731 743 post :copy, :id => 1, :project => {:name => 'Copy', :identifier => ''}
732 744 assert_response :success
733 745 assert_select_error /Identifier cannot be blank/
734 746 end
735 747
736 748 def test_jump_should_redirect_to_active_tab
737 749 get :show, :id => 1, :jump => 'issues'
738 750 assert_redirected_to '/projects/ecookbook/issues'
739 751 end
740 752
741 753 def test_jump_should_not_redirect_to_inactive_tab
742 754 get :show, :id => 3, :jump => 'documents'
743 755 assert_response :success
744 756 end
745 757
746 758 def test_jump_should_not_redirect_to_unknown_tab
747 759 get :show, :id => 3, :jump => 'foobar'
748 760 assert_response :success
749 761 end
750 762
751 763 def test_body_should_have_project_css_class
752 764 get :show, :id => 1
753 765 assert_select 'body.project-ecookbook'
754 766 end
755 767 end
@@ -1,158 +1,164
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class Redmine::ApiTest::MembershipsTest < Redmine::ApiTest::Base
21 21 fixtures :projects, :users, :roles, :members, :member_roles
22 22
23 23 test "GET /projects/:project_id/memberships.xml should return memberships" do
24 24 get '/projects/1/memberships.xml', {}, credentials('jsmith')
25 25
26 26 assert_response :success
27 27 assert_equal 'application/xml', @response.content_type
28 28 assert_select 'memberships[type=array] membership id', :text => '2' do
29 29 assert_select '~ user[id="3"][name="Dave Lopper"]'
30 30 assert_select '~ roles role[id="2"][name=Developer]'
31 31 end
32 32 end
33 33
34 34 test "GET /projects/:project_id/memberships.json should return memberships" do
35 35 get '/projects/1/memberships.json', {}, credentials('jsmith')
36 36
37 37 assert_response :success
38 38 assert_equal 'application/json', @response.content_type
39 39 json = ActiveSupport::JSON.decode(response.body)
40 assert_equal({
41 "memberships" =>
42 [{"id"=>1,
43 "project" => {"name"=>"eCookbook", "id"=>1},
44 "roles" => [{"name"=>"Manager", "id"=>1}],
45 "user" => {"name"=>"John Smith", "id"=>2}},
46 {"id"=>2,
47 "project" => {"name"=>"eCookbook", "id"=>1},
48 "roles" => [{"name"=>"Developer", "id"=>2}],
49 "user" => {"name"=>"Dave Lopper", "id"=>3}}],
50 "limit" => 25,
51 "total_count" => 2,
52 "offset" => 0},
53 json)
40 assert_equal 3, json["total_count"]
41 assert_equal 25, json["limit"]
42 assert_equal 0, json["offset"]
43 assert_include({
44 "id"=>1,
45 "project" => {"name"=>"eCookbook", "id"=>1},
46 "roles" => [{"name"=>"Manager", "id"=>1}],
47 "user" => {"name"=>"John Smith", "id"=>2}
48 },
49 json["memberships"]
50 )
54 51 end
55 52
56 53 test "GET /projects/:project_id/memberships.xml should succeed for closed project" do
57 54 project = Project.find(1)
58 55 project.close
59 56 assert !project.reload.active?
60 57 get '/projects/1/memberships.json', {}, credentials('jsmith')
61 58 assert_response :success
62 59 end
63 60
61 test "GET /projects/:project_id/memberships.xml should include locked users" do
62 assert User.find(3).lock!
63 get '/projects/ecookbook/memberships.xml', {}, credentials('jsmith')
64 assert_response :success
65 assert_select 'memberships[type=array] membership id', :text => '2' do
66 assert_select '~ user[id="3"][name="Dave Lopper"]'
67 end
68 end
69
64 70 test "POST /projects/:project_id/memberships.xml should create the membership" do
65 71 assert_difference 'Member.count' do
66 72 post '/projects/1/memberships.xml', {:membership => {:user_id => 7, :role_ids => [2,3]}}, credentials('jsmith')
67 73
68 74 assert_response :created
69 75 end
70 76 end
71 77
72 78 test "POST /projects/:project_id/memberships.xml should create the group membership" do
73 79 group = Group.find(11)
74 80
75 81 assert_difference 'Member.count', 1 + group.users.count do
76 82 post '/projects/1/memberships.xml', {:membership => {:user_id => 11, :role_ids => [2,3]}}, credentials('jsmith')
77 83
78 84 assert_response :created
79 85 end
80 86 end
81 87
82 88 test "POST /projects/:project_id/memberships.xml with invalid parameters should return errors" do
83 89 assert_no_difference 'Member.count' do
84 90 post '/projects/1/memberships.xml', {:membership => {:role_ids => [2,3]}}, credentials('jsmith')
85 91
86 92 assert_response :unprocessable_entity
87 93 assert_equal 'application/xml', @response.content_type
88 94 assert_select 'errors error', :text => "Principal cannot be blank"
89 95 end
90 96 end
91 97
92 98 test "GET /memberships/:id.xml should return the membership" do
93 99 get '/memberships/2.xml', {}, credentials('jsmith')
94 100
95 101 assert_response :success
96 102 assert_equal 'application/xml', @response.content_type
97 103 assert_select 'membership id', :text => '2' do
98 104 assert_select '~ user[id="3"][name="Dave Lopper"]'
99 105 assert_select '~ roles role[id="2"][name=Developer]'
100 106 end
101 107 end
102 108
103 109 test "GET /memberships/:id.json should return the membership" do
104 110 get '/memberships/2.json', {}, credentials('jsmith')
105 111
106 112 assert_response :success
107 113 assert_equal 'application/json', @response.content_type
108 114 json = ActiveSupport::JSON.decode(response.body)
109 115 assert_equal(
110 116 {"membership" => {
111 117 "id" => 2,
112 118 "project" => {"name"=>"eCookbook", "id"=>1},
113 119 "roles" => [{"name"=>"Developer", "id"=>2}],
114 120 "user" => {"name"=>"Dave Lopper", "id"=>3}}
115 121 },
116 122 json)
117 123 end
118 124
119 125 test "PUT /memberships/:id.xml should update the membership" do
120 126 assert_not_equal [1,2], Member.find(2).role_ids.sort
121 127 assert_no_difference 'Member.count' do
122 128 put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [1,2]}}, credentials('jsmith')
123 129
124 130 assert_response :ok
125 131 assert_equal '', @response.body
126 132 end
127 133 member = Member.find(2)
128 134 assert_equal [1,2], member.role_ids.sort
129 135 end
130 136
131 137 test "PUT /memberships/:id.xml with invalid parameters should return errors" do
132 138 put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [99]}}, credentials('jsmith')
133 139
134 140 assert_response :unprocessable_entity
135 141 assert_equal 'application/xml', @response.content_type
136 142 assert_select 'errors error', :text => "Role cannot be empty"
137 143 end
138 144
139 145 test "DELETE /memberships/:id.xml should destroy the membership" do
140 146 assert_difference 'Member.count', -1 do
141 147 delete '/memberships/2.xml', {}, credentials('jsmith')
142 148
143 149 assert_response :ok
144 150 assert_equal '', @response.body
145 151 end
146 152 assert_nil Member.find_by_id(2)
147 153 end
148 154
149 155 test "DELETE /memberships/:id.xml should respond with 422 on failure" do
150 156 assert_no_difference 'Member.count' do
151 157 # A membership with an inherited role cannot be deleted
152 158 Member.find(2).member_roles.first.update_attribute :inherited_from, 99
153 159 delete '/memberships/2.xml', {}, credentials('jsmith')
154 160
155 161 assert_response :unprocessable_entity
156 162 end
157 163 end
158 164 end
General Comments 0
You need to be logged in to leave comments. Login now