Commit 439a61783d0b61bbcc8f3c9e5b828b2270a679aa
1 parent
c86553cd
Exists in
spb-stable
and in
3 other branches
User can leave group from group page.
Showing
23 changed files
with
430 additions
and
151 deletions
Show diff stats
app/controllers/application_controller.rb
... | ... | @@ -135,12 +135,12 @@ class ApplicationController < ActionController::Base |
135 | 135 | end |
136 | 136 | end |
137 | 137 | |
138 | - def render_404 | |
139 | - render file: Rails.root.join("public", "404"), layout: false, status: "404" | |
138 | + def render_403 | |
139 | + head :forbidden | |
140 | 140 | end |
141 | 141 | |
142 | - def render_403 | |
143 | - render file: Rails.root.join("public", "403"), layout: false, status: "403" | |
142 | + def render_404 | |
143 | + render file: Rails.root.join("public", "404"), layout: false, status: "404" | |
144 | 144 | end |
145 | 145 | |
146 | 146 | def require_non_empty_project | ... | ... |
app/controllers/profiles/groups_controller.rb
... | ... | @@ -7,12 +7,11 @@ class Profiles::GroupsController < ApplicationController |
7 | 7 | |
8 | 8 | def leave |
9 | 9 | @users_group = group.users_groups.where(user_id: current_user.id).first |
10 | - | |
11 | - if group.last_owner?(current_user) | |
12 | - redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.") | |
13 | - else | |
10 | + if can?(current_user, :destroy, @users_group) | |
14 | 11 | @users_group.destroy |
15 | 12 | redirect_to(profile_groups_path, info: "You left #{group.name} group.") |
13 | + else | |
14 | + return render_403 | |
16 | 15 | end |
17 | 16 | end |
18 | 17 | ... | ... |
app/controllers/users_groups_controller.rb
... | ... | @@ -19,11 +19,14 @@ class UsersGroupsController < ApplicationController |
19 | 19 | |
20 | 20 | def destroy |
21 | 21 | @users_group = @group.users_groups.find(params[:id]) |
22 | - @users_group.destroy | |
23 | - | |
24 | - respond_to do |format| | |
25 | - format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' } | |
26 | - format.js { render nothing: true } | |
22 | + if can?(current_user, :destroy, @users_group) # May fail if last owner. | |
23 | + @users_group.destroy | |
24 | + respond_to do |format| | |
25 | + format.html { redirect_to members_group_path(@group), notice: 'User was successfully removed from group.' } | |
26 | + format.js { render nothing: true } | |
27 | + end | |
28 | + else | |
29 | + return render_403 | |
27 | 30 | end |
28 | 31 | end |
29 | 32 | ... | ... |
app/helpers/groups_helper.rb
1 | 1 | module GroupsHelper |
2 | 2 | def remove_user_from_group_message(group, user) |
3 | - "You are going to remove #{user.name} from #{group.name} Group. Are you sure?" | |
3 | + "Are you sure you want to remove \"#{user.name}\" from \"#{group.name}\"?" | |
4 | + end | |
5 | + | |
6 | + def leave_group_message(group) | |
7 | + "Are you sure you want to leave \"#{group}\" group?" | |
4 | 8 | end |
5 | 9 | |
6 | 10 | def group_head_title | ... | ... |
app/models/ability.rb
... | ... | @@ -14,6 +14,7 @@ class Ability |
14 | 14 | when "MergeRequest" then merge_request_abilities(user, subject) |
15 | 15 | when "Group" then group_abilities(user, subject) |
16 | 16 | when "Namespace" then namespace_abilities(user, subject) |
17 | + when "UsersGroup" then users_group_abilities(user, subject) | |
17 | 18 | else [] |
18 | 19 | end.concat(global_abilities(user)) |
19 | 20 | end |
... | ... | @@ -219,5 +220,19 @@ class Ability |
219 | 220 | end |
220 | 221 | end |
221 | 222 | end |
223 | + | |
224 | + def users_group_abilities(user, subject) | |
225 | + rules = [] | |
226 | + target_user = subject.user | |
227 | + group = subject.group | |
228 | + can_manage = group_abilities(user, group).include?(:manage_group) | |
229 | + if can_manage && (user != target_user) | |
230 | + rules << :modify | |
231 | + end | |
232 | + if !group.last_owner?(user) && (can_manage || (user == target_user)) | |
233 | + rules << :destroy | |
234 | + end | |
235 | + rules | |
236 | + end | |
222 | 237 | end |
223 | 238 | end | ... | ... |
app/views/groups/members.html.haml
... | ... | @@ -6,7 +6,6 @@ |
6 | 6 | %strong= link_to "here", help_permissions_path, class: "vlink" |
7 | 7 | |
8 | 8 | %hr |
9 | -- can_manage_group = current_user.can? :manage_group, @group | |
10 | 9 | .ui-box |
11 | 10 | .title |
12 | 11 | %strong #{@group.name} |
... | ... | @@ -15,6 +14,6 @@ |
15 | 14 | (#{@members.count}) |
16 | 15 | %ul.well-list |
17 | 16 | - @members.each do |member| |
18 | - = render 'users_groups/users_group', member: member, show_controls: can_manage_group | |
19 | -- if can_manage_group | |
17 | + = render 'users_groups/users_group', member: member, show_controls: true | |
18 | +- if current_user.can? :manage_group, @group | |
20 | 19 | = render "new_group_member" | ... | ... |
app/views/help/permissions.html.haml
app/views/profiles/groups/index.html.haml
... | ... | @@ -22,9 +22,10 @@ |
22 | 22 | %i.icon-cogs |
23 | 23 | Settings |
24 | 24 | |
25 | - = link_to leave_profile_group_path(group), data: { confirm: "Are you sure you want to leave #{group.name} group?"}, method: :delete, class: "btn-small btn grouped", title: 'Remove user from group' do | |
26 | - %i.icon-signout | |
27 | - Leave | |
25 | + - if can?(current_user, :destroy, user_group) | |
26 | + = link_to leave_profile_group_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-small btn grouped", title: 'Remove user from group' do | |
27 | + %i.icon-signout | |
28 | + Leave | |
28 | 29 | |
29 | 30 | = link_to group, class: 'group-name' do |
30 | 31 | %strong= group.name | ... | ... |
app/views/users_groups/_users_group.html.haml
... | ... | @@ -9,12 +9,17 @@ |
9 | 9 | |
10 | 10 | %span.pull-right |
11 | 11 | %strong= member.human_access |
12 | - | |
13 | - - if show_controls && can?(current_user, :manage_group, @group) && current_user != user | |
14 | - = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do | |
15 | - %i.icon-edit | |
16 | - = link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do | |
17 | - %i.icon-minus.icon-white | |
12 | + - if show_controls | |
13 | + - if can?(current_user, :modify, member) | |
14 | + = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do | |
15 | + %i.icon-edit | |
16 | + - if can?(current_user, :destroy, member) | |
17 | + - if current_user == member.user | |
18 | + = link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do | |
19 | + %i.icon-minus.icon-white | |
20 | + - else | |
21 | + = link_to group_users_group_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do | |
22 | + %i.icon-minus.icon-white | |
18 | 23 | |
19 | 24 | .edit-member.hide.js-toggle-content |
20 | 25 | = form_for [@group, member], remote: true do |f| | ... | ... |
features/admin/groups.feature
... | ... | @@ -0,0 +1,116 @@ |
1 | +Feature: Groups | |
2 | + Background: | |
3 | + Given I sign in as "John Doe" | |
4 | + And "John Doe" is owner of group "Owned" | |
5 | + And "John Doe" is guest of group "Guest" | |
6 | + | |
7 | + @javascript | |
8 | + Scenario: I should see group "Owned" dashboard list | |
9 | + When I visit group "Owned" page | |
10 | + Then I should see group "Owned" projects list | |
11 | + And I should see projects activity feed | |
12 | + | |
13 | + Scenario: Create a group from dasboard | |
14 | + When I visit group "Owned" page | |
15 | + And I visit dashboard page | |
16 | + And I click new group link | |
17 | + And submit form with new group "Samurai" info | |
18 | + Then I should be redirected to group "Samurai" page | |
19 | + And I should see newly created group "Samurai" | |
20 | + | |
21 | + Scenario: I should see group "Owned" issues list | |
22 | + Given project from group "Owned" has issues assigned to me | |
23 | + When I visit group "Owned" issues page | |
24 | + Then I should see issues from group "Owned" assigned to me | |
25 | + | |
26 | + Scenario: I should see group "Owned" merge requests list | |
27 | + Given project from group "Owned" has merge requests assigned to me | |
28 | + When I visit group "Owned" merge requests page | |
29 | + Then I should see merge requests from group "Owned" assigned to me | |
30 | + | |
31 | + @javascript | |
32 | + Scenario: I should add user to projects in group "Owned" | |
33 | + Given User "Mary Jane" exists | |
34 | + When I visit group "Owned" members page | |
35 | + And I select user "Mary Jane" from list with role "Reporter" | |
36 | + Then I should see user "Mary Jane" in team list | |
37 | + | |
38 | + Scenario: I should see edit group "Owned" page | |
39 | + When I visit group "Owned" settings page | |
40 | + And I change group "Owned" name to "new-name" | |
41 | + Then I should see new group "Owned" name | |
42 | + | |
43 | + Scenario: I edit group "Owned" avatar | |
44 | + When I visit group "Owned" settings page | |
45 | + And I change group "Owned" avatar | |
46 | + And I visit group "Owned" settings page | |
47 | + Then I should see new group "Owned" avatar | |
48 | + And I should see the "Remove avatar" button | |
49 | + | |
50 | + Scenario: I remove group "Owned" avatar | |
51 | + When I visit group "Owned" settings page | |
52 | + And I have group "Owned" avatar | |
53 | + And I visit group "Owned" settings page | |
54 | + And I remove group "Owned" avatar | |
55 | + Then I should not see group "Owned" avatar | |
56 | + And I should not see the "Remove avatar" button | |
57 | + | |
58 | + # Leave | |
59 | + | |
60 | + @javascript | |
61 | + Scenario: Owner should be able to remove himself from group if he is not the last owner | |
62 | + Given "Mary Jane" is owner of group "Owned" | |
63 | + When I visit group "Owned" members page | |
64 | + Then I should see user "John Doe" in team list | |
65 | + Then I should see user "Mary Jane" in team list | |
66 | + When I click on the "Remove User From Group" button for "John Doe" | |
67 | + And I visit group "Owned" members page | |
68 | + Then I should not see user "John Doe" in team list | |
69 | + Then I should see user "Mary Jane" in team list | |
70 | + | |
71 | + @javascript | |
72 | + Scenario: Owner should not be able to remove himself from group if he is the last owner | |
73 | + Given "Mary Jane" is guest of group "Owned" | |
74 | + When I visit group "Owned" members page | |
75 | + Then I should see user "John Doe" in team list | |
76 | + Then I should see user "Mary Jane" in team list | |
77 | + Then I should not see the "Remove User From Group" button for "Mary Jane" | |
78 | + | |
79 | + @javascript | |
80 | + Scenario: Guest should be able to remove himself from group | |
81 | + Given "Mary Jane" is guest of group "Guest" | |
82 | + When I visit group "Guest" members page | |
83 | + Then I should see user "John Doe" in team list | |
84 | + Then I should see user "Mary Jane" in team list | |
85 | + When I click on the "Remove User From Group" button for "John Doe" | |
86 | + When I visit group "Guest" members page | |
87 | + Then I should not see user "John Doe" in team list | |
88 | + Then I should see user "Mary Jane" in team list | |
89 | + | |
90 | + @javascript | |
91 | + Scenario: Guest should be able to remove himself from group even if he is the only user in the group | |
92 | + When I visit group "Guest" members page | |
93 | + Then I should see user "John Doe" in team list | |
94 | + When I click on the "Remove User From Group" button for "John Doe" | |
95 | + When I visit group "Guest" members page | |
96 | + Then I should not see user "John Doe" in team list | |
97 | + | |
98 | + # Remove others | |
99 | + | |
100 | + @javascript | |
101 | + Scenario: Owner should be able to remove other users from group | |
102 | + Given "Mary Jane" is owner of group "Owned" | |
103 | + When I visit group "Owned" members page | |
104 | + Then I should see user "John Doe" in team list | |
105 | + Then I should see user "Mary Jane" in team list | |
106 | + When I click on the "Remove User From Group" button for "Mary Jane" | |
107 | + When I visit group "Owned" members page | |
108 | + Then I should see user "John Doe" in team list | |
109 | + Then I should not see user "Mary Jane" in team list | |
110 | + | |
111 | + Scenario: Guest should not be able to remove other users from group | |
112 | + Given "Mary Jane" is guest of group "Guest" | |
113 | + When I visit group "Guest" members page | |
114 | + Then I should see user "John Doe" in team list | |
115 | + Then I should see user "Mary Jane" in team list | |
116 | + Then I should not see the "Remove User From Group" button for "Mary Jane" | ... | ... |
features/group/create_group.feature
... | ... | @@ -1,11 +0,0 @@ |
1 | -Feature: Groups | |
2 | - Background: | |
3 | - Given I sign in as a user | |
4 | - | |
5 | - Scenario: Create a group from dasboard | |
6 | - Given I have group with projects | |
7 | - And I visit dashboard page | |
8 | - When I click new group link | |
9 | - And submit form with new group info | |
10 | - Then I should be redirected to group page | |
11 | - And I should see newly created group |
features/group/group.feature
... | ... | @@ -1,47 +0,0 @@ |
1 | -Feature: Groups | |
2 | - Background: | |
3 | - Given I sign in as a user | |
4 | - And I have group with projects | |
5 | - | |
6 | - @javascript | |
7 | - Scenario: I should see group dashboard list | |
8 | - When I visit group page | |
9 | - Then I should see projects list | |
10 | - And I should see projects activity feed | |
11 | - | |
12 | - Scenario: I should see group issues list | |
13 | - Given project from group has issues assigned to me | |
14 | - When I visit group issues page | |
15 | - Then I should see issues from this group assigned to me | |
16 | - | |
17 | - Scenario: I should see group merge requests list | |
18 | - Given project from group has merge requests assigned to me | |
19 | - When I visit group merge requests page | |
20 | - Then I should see merge requests from this group assigned to me | |
21 | - | |
22 | - @javascript | |
23 | - Scenario: I should add user to projects in Group | |
24 | - Given Create user "John Doe" | |
25 | - When I visit group members page | |
26 | - And I select user "John Doe" from list with role "Reporter" | |
27 | - Then I should see user "John Doe" in team list | |
28 | - | |
29 | - Scenario: I should see edit group page | |
30 | - When I visit group settings page | |
31 | - And I change group name | |
32 | - Then I should see new group name | |
33 | - | |
34 | - Scenario: I edit my group avatar | |
35 | - When I visit group settings page | |
36 | - And I change my group avatar | |
37 | - And I visit group settings page | |
38 | - Then I should see new group avatar | |
39 | - And I should see the "Remove avatar" button | |
40 | - | |
41 | - Scenario: I remove my group avatar | |
42 | - When I visit group settings page | |
43 | - And I have an group avatar | |
44 | - And I visit group settings page | |
45 | - And I remove my group avatar | |
46 | - Then I should not see my group avatar | |
47 | - And I should not see the "Remove avatar" button |
... | ... | @@ -0,0 +1,47 @@ |
1 | +Feature: Profile Group | |
2 | + Background: | |
3 | + Given I sign in as "John Doe" | |
4 | + And "John Doe" is owner of group "Owned" | |
5 | + And "John Doe" is guest of group "Guest" | |
6 | + | |
7 | + # Leave groups | |
8 | + | |
9 | + @javascript | |
10 | + Scenario: Owner should be able to leave from group if he is not the last owner | |
11 | + Given "Mary Jane" is owner of group "Owned" | |
12 | + When I visit profile groups page | |
13 | + Then I should see group "Owned" in group list | |
14 | + Then I should see group "Guest" in group list | |
15 | + When I click on the "Leave" button for group "Owned" | |
16 | + And I visit profile groups page | |
17 | + Then I should not see group "Owned" in group list | |
18 | + Then I should see group "Guest" in group list | |
19 | + | |
20 | + @javascript | |
21 | + Scenario: Owner should not be able to leave from group if he is the last owner | |
22 | + Given "Mary Jane" is guest of group "Owned" | |
23 | + When I visit profile groups page | |
24 | + Then I should see group "Owned" in group list | |
25 | + Then I should see group "Guest" in group list | |
26 | + Then I should not see the "Leave" button for group "Owned" | |
27 | + | |
28 | + @javascript | |
29 | + Scenario: Guest should be able to leave from group | |
30 | + Given "Mary Jane" is guest of group "Guest" | |
31 | + When I visit profile groups page | |
32 | + Then I should see group "Owned" in group list | |
33 | + Then I should see group "Guest" in group list | |
34 | + When I click on the "Leave" button for group "Guest" | |
35 | + When I visit profile groups page | |
36 | + Then I should see group "Owned" in group list | |
37 | + Then I should not see group "Guest" in group list | |
38 | + | |
39 | + @javascript | |
40 | + Scenario: Guest should be able to leave from group even if he is the only user in the group | |
41 | + When I visit profile groups page | |
42 | + Then I should see group "Owned" in group list | |
43 | + Then I should see group "Guest" in group list | |
44 | + When I click on the "Leave" button for group "Guest" | |
45 | + When I visit profile groups page | |
46 | + Then I should see group "Owned" in group list | |
47 | + Then I should not see group "Guest" in group list | ... | ... |
features/steps/group/group.rb
1 | 1 | class Groups < Spinach::FeatureSteps |
2 | 2 | include SharedAuthentication |
3 | 3 | include SharedPaths |
4 | + include SharedGroup | |
4 | 5 | include SharedUser |
5 | 6 | include Select2Helper |
6 | 7 | |
7 | - Then 'I should see projects list' do | |
8 | - current_user.authorized_projects.each do |project| | |
8 | + Then 'I should see group "Owned" projects list' do | |
9 | + Group.find_by(name: "Owned").projects.each do |project| | |
9 | 10 | page.should have_link project.name |
10 | 11 | end |
11 | 12 | end |
12 | 13 | |
13 | - And 'I have group with projects' do | |
14 | - @group = create(:group) | |
15 | - @group.add_owner(current_user) | |
16 | - @project = create(:project, namespace: @group) | |
17 | - @event = create(:closed_issue_event, project: @project) | |
18 | - | |
19 | - @project.team << [current_user, :master] | |
20 | - end | |
21 | - | |
22 | 14 | And 'I should see projects activity feed' do |
23 | 15 | page.should have_content 'closed issue' |
24 | 16 | end |
25 | 17 | |
26 | - Then 'I should see issues from this group assigned to me' do | |
18 | + Then 'I should see issues from group "Owned" assigned to me' do | |
27 | 19 | assigned_to_me(:issues).each do |issue| |
28 | 20 | page.should have_content issue.title |
29 | 21 | end |
30 | 22 | end |
31 | 23 | |
32 | - Then 'I should see merge requests from this group assigned to me' do | |
24 | + Then 'I should see merge requests from group "Owned" assigned to me' do | |
33 | 25 | assigned_to_me(:merge_requests).each do |issue| |
34 | 26 | page.should have_content issue.title[0..80] |
35 | 27 | end |
36 | 28 | end |
37 | 29 | |
38 | - And 'I select user "John Doe" from list with role "Reporter"' do | |
39 | - user = User.find_by(name: "John Doe") | |
30 | + And 'I select user "Mary Jane" from list with role "Reporter"' do | |
31 | + user = User.find_by(name: "Mary Jane") || create(:user, name: "Mary Jane") | |
40 | 32 | within ".users-group-form" do |
41 | 33 | select2(user.id, from: "#user_ids", multiple: true) |
42 | 34 | select "Reporter", from: "group_access" |
... | ... | @@ -49,14 +41,29 @@ class Groups < Spinach::FeatureSteps |
49 | 41 | projects_with_access.should have_content("John Doe") |
50 | 42 | end |
51 | 43 | |
52 | - Given 'project from group has issues assigned to me' do | |
44 | + Then 'I should not see user "John Doe" in team list' do | |
45 | + projects_with_access = find(".ui-box .well-list") | |
46 | + projects_with_access.should_not have_content("John Doe") | |
47 | + end | |
48 | + | |
49 | + Then 'I should see user "Mary Jane" in team list' do | |
50 | + projects_with_access = find(".ui-box .well-list") | |
51 | + projects_with_access.should have_content("Mary Jane") | |
52 | + end | |
53 | + | |
54 | + Then 'I should not see user "Mary Jane" in team list' do | |
55 | + projects_with_access = find(".ui-box .well-list") | |
56 | + projects_with_access.should_not have_content("Mary Jane") | |
57 | + end | |
58 | + | |
59 | + Given 'project from group "Owned" has issues assigned to me' do | |
53 | 60 | create :issue, |
54 | 61 | project: project, |
55 | 62 | assignee: current_user, |
56 | 63 | author: current_user |
57 | 64 | end |
58 | 65 | |
59 | - Given 'project from group has merge requests assigned to me' do | |
66 | + Given 'project from group "Owned" has merge requests assigned to me' do | |
60 | 67 | create :merge_request, |
61 | 68 | source_project: project, |
62 | 69 | target_project: project, |
... | ... | @@ -68,78 +75,94 @@ class Groups < Spinach::FeatureSteps |
68 | 75 | click_link "New group" |
69 | 76 | end |
70 | 77 | |
71 | - And 'submit form with new group info' do | |
78 | + And 'submit form with new group "Samurai" info' do | |
72 | 79 | fill_in 'group_name', with: 'Samurai' |
73 | 80 | fill_in 'group_description', with: 'Tokugawa Shogunate' |
74 | 81 | click_button "Create group" |
75 | 82 | end |
76 | 83 | |
77 | - Then 'I should see newly created group' do | |
84 | + Then 'I should be redirected to group "Samurai" page' do | |
85 | + current_path.should == group_path(Group.last) | |
86 | + end | |
87 | + | |
88 | + Then 'I should see newly created group "Samurai"' do | |
78 | 89 | page.should have_content "Samurai" |
79 | 90 | page.should have_content "Tokugawa Shogunate" |
80 | 91 | page.should have_content "You will only see events from projects in this group" |
81 | 92 | end |
82 | 93 | |
83 | - Then 'I should be redirected to group page' do | |
84 | - current_path.should == group_path(Group.last) | |
85 | - end | |
86 | - | |
87 | - And 'I change group name' do | |
94 | + And 'I change group "Owned" name to "new-name"' do | |
88 | 95 | fill_in 'group_name', with: 'new-name' |
89 | 96 | click_button "Save group" |
90 | 97 | end |
91 | 98 | |
92 | - Then 'I should see new group name' do | |
99 | + Then 'I should see new group "Owned" name' do | |
93 | 100 | within ".navbar-gitlab" do |
94 | 101 | page.should have_content "group: new-name" |
95 | 102 | end |
96 | 103 | end |
97 | 104 | |
98 | - step 'I change my group avatar' do | |
105 | + step 'I change group "Owned" avatar' do | |
99 | 106 | attach_file(:group_avatar, File.join(Rails.root, 'public', 'gitlab_logo.png')) |
100 | 107 | click_button "Save group" |
101 | - @group.reload | |
108 | + Group.find_by(name: "Owned").reload | |
102 | 109 | end |
103 | 110 | |
104 | - step 'I should see new group avatar' do | |
105 | - @group.avatar.should be_instance_of AttachmentUploader | |
106 | - @group.avatar.url.should == "/uploads/group/avatar/#{ @group.id }/gitlab_logo.png" | |
111 | + step 'I should see new group "Owned" avatar' do | |
112 | + Group.find_by(name: "Owned").avatar.should be_instance_of AttachmentUploader | |
113 | + Group.find_by(name: "Owned").avatar.url.should == "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/gitlab_logo.png" | |
107 | 114 | end |
108 | 115 | |
109 | 116 | step 'I should see the "Remove avatar" button' do |
110 | 117 | page.should have_link("Remove avatar") |
111 | 118 | end |
112 | 119 | |
113 | - step 'I have an group avatar' do | |
120 | + step 'I have group "Owned" avatar' do | |
114 | 121 | attach_file(:group_avatar, File.join(Rails.root, 'public', 'gitlab_logo.png')) |
115 | 122 | click_button "Save group" |
116 | - @group.reload | |
123 | + Group.find_by(name: "Owned").reload | |
117 | 124 | end |
118 | 125 | |
119 | - step 'I remove my group avatar' do | |
126 | + step 'I remove group "Owned" avatar' do | |
120 | 127 | click_link "Remove avatar" |
121 | - @group.reload | |
128 | + Group.find_by(name: "Owned").reload | |
122 | 129 | end |
123 | 130 | |
124 | - step 'I should not see my group avatar' do | |
125 | - @group.avatar?.should be_false | |
131 | + step 'I should not see group "Owned" avatar' do | |
132 | + Group.find_by(name: "Owned").avatar?.should be_false | |
126 | 133 | end |
127 | 134 | |
128 | 135 | step 'I should not see the "Remove avatar" button' do |
129 | 136 | page.should_not have_link("Remove avatar") |
130 | 137 | end |
131 | 138 | |
132 | - protected | |
139 | + step 'I click on the "Remove User From Group" button for "John Doe"' do | |
140 | + find(:css, 'li', text: "John Doe").find(:css, 'a.btn-remove').click | |
141 | + # poltergeist always confirms popups. | |
142 | + end | |
133 | 143 | |
134 | - def current_group | |
135 | - @group ||= Group.first | |
144 | + step 'I click on the "Remove User From Group" button for "Mary Jane"' do | |
145 | + find(:css, 'li', text: "Mary Jane").find(:css, 'a.btn-remove').click | |
146 | + # poltergeist always confirms popups. | |
136 | 147 | end |
137 | 148 | |
138 | - def project | |
139 | - current_group.projects.first | |
149 | + step 'I should not see the "Remove User From Group" button for "John Doe"' do | |
150 | + find(:css, 'li', text: "John Doe").should_not have_selector(:css, 'a.btn-remove') | |
151 | + # poltergeist always confirms popups. | |
140 | 152 | end |
141 | 153 | |
154 | + step 'I should not see the "Remove User From Group" button for "Mary Jane"' do | |
155 | + find(:css, 'li', text: "Mary Jane").should_not have_selector(:css, 'a.btn-remove') | |
156 | + # poltergeist always confirms popups. | |
157 | + end | |
158 | + | |
159 | + protected | |
160 | + | |
142 | 161 | def assigned_to_me key |
143 | 162 | project.send(key).where(assignee_id: current_user.id) |
144 | 163 | end |
164 | + | |
165 | + def project | |
166 | + Group.find_by(name: "Owned").projects.first | |
167 | + end | |
145 | 168 | end | ... | ... |
... | ... | @@ -0,0 +1,44 @@ |
1 | +class ProfileGroup < Spinach::FeatureSteps | |
2 | + include SharedAuthentication | |
3 | + include SharedGroup | |
4 | + include SharedPaths | |
5 | + include SharedUser | |
6 | + | |
7 | + # Leave | |
8 | + | |
9 | + step 'I click on the "Leave" button for group "Owned"' do | |
10 | + find(:css, 'li', text: "Owner").find(:css, 'i.icon-signout').click | |
11 | + # poltergeist always confirms popups. | |
12 | + end | |
13 | + | |
14 | + step 'I click on the "Leave" button for group "Guest"' do | |
15 | + find(:css, 'li', text: "Guest").find(:css, 'i.icon-signout').click | |
16 | + # poltergeist always confirms popups. | |
17 | + end | |
18 | + | |
19 | + step 'I should not see the "Leave" button for group "Owned"' do | |
20 | + find(:css, 'li', text: "Owner").should_not have_selector(:css, 'i.icon-signout') | |
21 | + # poltergeist always confirms popups. | |
22 | + end | |
23 | + | |
24 | + step 'I should not see the "Leave" button for groupr "Guest"' do | |
25 | + find(:css, 'li', text: "Guest").should_not have_selector(:css, 'i.icon-signout') | |
26 | + # poltergeist always confirms popups. | |
27 | + end | |
28 | + | |
29 | + step 'I should see group "Owned" in group list' do | |
30 | + page.should have_content("Owned") | |
31 | + end | |
32 | + | |
33 | + step 'I should not see group "Owned" in group list' do | |
34 | + page.should_not have_content("Owned") | |
35 | + end | |
36 | + | |
37 | + step 'I should see group "Guest" in group list' do | |
38 | + page.should have_content("Guest") | |
39 | + end | |
40 | + | |
41 | + step 'I should not see group "Guest" in group list' do | |
42 | + page.should_not have_content("Guest") | |
43 | + end | |
44 | +end | ... | ... |
features/steps/project/project_network_graph.rb
features/steps/shared/authentication.rb
... | ... | @@ -12,6 +12,14 @@ module SharedAuthentication |
12 | 12 | login_as :admin |
13 | 13 | end |
14 | 14 | |
15 | + step 'I sign in as "John Doe"' do | |
16 | + login_with(user_exists("John Doe")) | |
17 | + end | |
18 | + | |
19 | + step 'I sign in as "Mary Jane"' do | |
20 | + login_with(user_exists("Mary Jane")) | |
21 | + end | |
22 | + | |
15 | 23 | step 'I should be redirected to sign in page' do |
16 | 24 | current_path.should == new_user_session_path |
17 | 25 | end | ... | ... |
... | ... | @@ -0,0 +1,36 @@ |
1 | +module SharedGroup | |
2 | + include Spinach::DSL | |
3 | + | |
4 | + step '"John Doe" is owner of group "Owned"' do | |
5 | + is_member_of("John Doe", "Owned", Gitlab::Access::OWNER) | |
6 | + end | |
7 | + | |
8 | + step '"John Doe" is guest of group "Guest"' do | |
9 | + is_member_of("John Doe", "Guest", Gitlab::Access::GUEST) | |
10 | + end | |
11 | + | |
12 | + step '"Mary Jane" is owner of group "Owned"' do | |
13 | + is_member_of("Mary Jane", "Owned", Gitlab::Access::OWNER) | |
14 | + end | |
15 | + | |
16 | + step '"Mary Jane" is guest of group "Owned"' do | |
17 | + is_member_of("Mary Jane", "Owned", Gitlab::Access::GUEST) | |
18 | + end | |
19 | + | |
20 | + step '"Mary Jane" is guest of group "Guest"' do | |
21 | + is_member_of("Mary Jane", "Guest", Gitlab::Access::GUEST) | |
22 | + end | |
23 | + | |
24 | + protected | |
25 | + | |
26 | + def is_member_of(username, groupname, role) | |
27 | + @project_count ||= 0 | |
28 | + user = User.find_by(name: username) || create(:user, name: username) | |
29 | + group = Group.find_by(name: groupname) || create(:group, name: groupname) | |
30 | + group.add_user(user, role) | |
31 | + project ||= create(:project, namespace: group, path: "project#{@project_count}") | |
32 | + event ||= create(:closed_issue_event, project: project) | |
33 | + project.team << [user, :master] | |
34 | + @project_count += 1 | |
35 | + end | |
36 | +end | ... | ... |
features/steps/shared/paths.rb
... | ... | @@ -17,24 +17,44 @@ module SharedPaths |
17 | 17 | # Group |
18 | 18 | # ---------------------------------------- |
19 | 19 | |
20 | - step 'I visit group page' do | |
21 | - visit group_path(current_group) | |
20 | + step 'I visit group "Owned" page' do | |
21 | + visit group_path(Group.find_by(name:"Owned")) | |
22 | 22 | end |
23 | 23 | |
24 | - step 'I visit group issues page' do | |
25 | - visit issues_group_path(current_group) | |
24 | + step 'I visit group "Owned" issues page' do | |
25 | + visit issues_group_path(Group.find_by(name:"Owned")) | |
26 | 26 | end |
27 | 27 | |
28 | - step 'I visit group merge requests page' do | |
29 | - visit merge_requests_group_path(current_group) | |
28 | + step 'I visit group "Owned" merge requests page' do | |
29 | + visit merge_requests_group_path(Group.find_by(name:"Owned")) | |
30 | 30 | end |
31 | 31 | |
32 | - step 'I visit group members page' do | |
33 | - visit members_group_path(current_group) | |
32 | + step 'I visit group "Owned" members page' do | |
33 | + visit members_group_path(Group.find_by(name:"Owned")) | |
34 | 34 | end |
35 | 35 | |
36 | - step 'I visit group settings page' do | |
37 | - visit edit_group_path(current_group) | |
36 | + step 'I visit group "Owned" settings page' do | |
37 | + visit edit_group_path(Group.find_by(name:"Owned")) | |
38 | + end | |
39 | + | |
40 | + step 'I visit group "Guest" page' do | |
41 | + visit group_path(Group.find_by(name:"Guest")) | |
42 | + end | |
43 | + | |
44 | + step 'I visit group "Guest" issues page' do | |
45 | + visit issues_group_path(Group.find_by(name:"Guest")) | |
46 | + end | |
47 | + | |
48 | + step 'I visit group "Guest" merge requests page' do | |
49 | + visit merge_requests_group_path(Group.find_by(name:"Guest")) | |
50 | + end | |
51 | + | |
52 | + step 'I visit group "Guest" members page' do | |
53 | + visit members_group_path(Group.find_by(name:"Guest")) | |
54 | + end | |
55 | + | |
56 | + step 'I visit group "Guest" settings page' do | |
57 | + visit edit_group_path(Group.find_by(name:"Guest")) | |
38 | 58 | end |
39 | 59 | |
40 | 60 | # ---------------------------------------- |
... | ... | @@ -93,6 +113,14 @@ module SharedPaths |
93 | 113 | visit history_profile_path |
94 | 114 | end |
95 | 115 | |
116 | + step 'I visit profile groups page' do | |
117 | + visit profile_groups_path | |
118 | + end | |
119 | + | |
120 | + step 'I should be redirected to the profile groups page' do | |
121 | + current_path.should == profile_groups_path | |
122 | + end | |
123 | + | |
96 | 124 | # ---------------------------------------- |
97 | 125 | # Admin |
98 | 126 | # ---------------------------------------- |
... | ... | @@ -326,4 +354,12 @@ module SharedPaths |
326 | 354 | def project |
327 | 355 | project = Project.find_by!(name: "Shop") |
328 | 356 | end |
357 | + | |
358 | + # ---------------------------------------- | |
359 | + # Errors | |
360 | + # ---------------------------------------- | |
361 | + | |
362 | + Then 'page status code should be 404' do | |
363 | + page.status_code.should == 404 | |
364 | + end | |
329 | 365 | end | ... | ... |
features/steps/shared/project.rb
... | ... | @@ -58,10 +58,6 @@ module SharedProject |
58 | 58 | page.should have_content("Features:") |
59 | 59 | end |
60 | 60 | |
61 | - Then 'page status code should be 404' do | |
62 | - page.status_code.should == 404 | |
63 | - end | |
64 | - | |
65 | 61 | def current_project |
66 | 62 | @project ||= Project.first |
67 | 63 | end |
... | ... | @@ -107,24 +103,21 @@ module SharedProject |
107 | 103 | end |
108 | 104 | |
109 | 105 | step '"John Doe" is authorized to private project "Enterprise"' do |
110 | - user = User.find_by(name: "John Doe") | |
111 | - user ||= create(:user, name: "John Doe", username: "john_doe") | |
106 | + user = user_exists("John Doe", username: "john_doe") | |
112 | 107 | project = Project.find_by(name: "Enterprise") |
113 | 108 | project ||= create(:project, name: "Enterprise", namespace: user.namespace) |
114 | 109 | project.team << [user, :master] |
115 | 110 | end |
116 | 111 | |
117 | 112 | step '"John Doe" is authorized to internal project "Internal"' do |
118 | - user = User.find_by(name: "John Doe") | |
119 | - user ||= create(:user, name: "John Doe", username: "john_doe") | |
113 | + user = user_exists("John Doe", username: "john_doe") | |
120 | 114 | project = Project.find_by(name: "Internal") |
121 | 115 | project ||= create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL |
122 | 116 | project.team << [user, :master] |
123 | 117 | end |
124 | 118 | |
125 | 119 | step '"John Doe" is authorized to public project "Community"' do |
126 | - user = User.find_by(name: "John Doe") | |
127 | - user ||= create(:user, name: "John Doe", username: "john_doe") | |
120 | + user = user_exists("John Doe", username: "john_doe") | |
128 | 121 | project = Project.find_by(name: "Community") |
129 | 122 | project ||= create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC |
130 | 123 | project.team << [user, :master] | ... | ... |
features/steps/shared/user.rb
1 | 1 | module SharedUser |
2 | 2 | include Spinach::DSL |
3 | 3 | |
4 | - step 'Create user "John Doe"' do | |
5 | - create(:user, name: "John Doe", username: "john_doe") | |
4 | + step 'User "John Doe" exists' do | |
5 | + user_exists("John Doe", {username: "john_doe"}) | |
6 | 6 | end |
7 | 7 | |
8 | - step 'I sign in as "John Doe"' do | |
9 | - login_with(User.find_by(name: "John Doe")) | |
8 | + step 'User "Mary Jane" exists' do | |
9 | + user_exists("Mary Jane", {username: "mary_jane"}) | |
10 | + end | |
11 | + | |
12 | + protected | |
13 | + | |
14 | + def user_exists(name, options = {}) | |
15 | + User.find_by(name: name) || create(:user, {name: name, admin: false}.merge(options)) | |
10 | 16 | end |
11 | 17 | end | ... | ... |