Commit 1692073d authored by Coung Ngo's avatar Coung Ngo

Disable editing for inherited iterations

Inherited iterations should not allow editing as editing
should only happen at the source iteration
parent 498292b1
...@@ -96,6 +96,9 @@ export default { ...@@ -96,6 +96,9 @@ export default {
}; };
}, },
computed: { computed: {
canEditIteration() {
return this.canEdit && this.namespaceType === Namespace.Group;
},
hasIteration() { hasIteration() {
return !this.$apollo.queries.iteration.loading && this.iteration?.title; return !this.$apollo.queries.iteration.loading && this.iteration?.title;
}, },
...@@ -155,7 +158,7 @@ export default { ...@@ -155,7 +158,7 @@ export default {
>{{ formatDate(iteration.startDate) }}{{ formatDate(iteration.dueDate) }}</span >{{ formatDate(iteration.startDate) }}{{ formatDate(iteration.dueDate) }}</span
> >
<gl-new-dropdown <gl-new-dropdown
v-if="canEdit" v-if="canEditIteration"
variant="default" variant="default"
toggle-class="gl-text-decoration-none gl-border-0! gl-shadow-none!" toggle-class="gl-text-decoration-none gl-border-0! gl-shadow-none!"
class="gl-ml-auto gl-text-secondary" class="gl-ml-auto gl-text-secondary"
......
...@@ -9,6 +9,7 @@ RSpec.describe 'User views iteration' do ...@@ -9,6 +9,7 @@ RSpec.describe 'User views iteration' do
let_it_be(:project) { create(:project, group: group) } let_it_be(:project) { create(:project, group: group) }
let_it_be(:sub_project) { create(:project, group: sub_group) } let_it_be(:sub_project) { create(:project, group: sub_group) }
let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user } let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user }
let_it_be(:guest_user) { create(:group_member, :guest, user: create(:user), group: group).user }
let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iid: 1, id: 2, group: group, title: 'Correct Iteration', start_date: now - 1.day, due_date: now) } let_it_be(:iteration) { create(:iteration, :skip_future_date_validation, iid: 1, id: 2, group: group, title: 'Correct Iteration', start_date: now - 1.day, due_date: now) }
let_it_be(:other_iteration) { create(:iteration, :skip_future_date_validation, iid: 2, id: 1, group: group, title: 'Wrong Iteration', start_date: now - 4.days, due_date: now - 3.days) } let_it_be(:other_iteration) { create(:iteration, :skip_future_date_validation, iid: 2, id: 1, group: group, title: 'Wrong Iteration', start_date: now - 4.days, due_date: now - 3.days) }
let_it_be(:sub_group_iteration) { create(:iteration, id: 3, group: sub_group) } let_it_be(:sub_group_iteration) { create(:iteration, id: 3, group: sub_group) }
...@@ -18,15 +19,13 @@ RSpec.describe 'User views iteration' do ...@@ -18,15 +19,13 @@ RSpec.describe 'User views iteration' do
let_it_be(:sub_group_issue) { create(:issue, project: sub_project, iteration: iteration) } let_it_be(:sub_group_issue) { create(:issue, project: sub_project, iteration: iteration) }
let_it_be(:other_issue) { create(:issue, project: project, iteration: other_iteration) } let_it_be(:other_issue) { create(:issue, project: project, iteration: other_iteration) }
context 'with license' do context 'with license', :js do
context 'view an iteration' do
before do before do
stub_licensed_features(iterations: true) stub_licensed_features(iterations: true)
sign_in(user) sign_in(user)
end
context 'view an iteration', :js do visit group_iteration_path(iteration.group, iteration.iid)
before do
visit group_iteration_path(group, iteration.iid)
end end
it 'shows iteration info and dates' do it 'shows iteration info and dates' do
...@@ -51,6 +50,32 @@ RSpec.describe 'User views iteration' do ...@@ -51,6 +50,32 @@ RSpec.describe 'User views iteration' do
expect(page).not_to have_content(other_issue.title) expect(page).not_to have_content(other_issue.title)
end end
end end
context 'when user has edit permissions' do
before do
stub_licensed_features(iterations: true)
sign_in(user)
visit group_iteration_path(iteration.group, iteration.iid)
end
it 'shows action dropdown for editing the iteration' do
expect(page).to have_button('Actions')
end
end
context 'when user does not have edit permissions' do
before do
stub_licensed_features(iterations: true)
sign_in(guest_user)
visit group_iteration_path(iteration.group, iteration.iid)
end
it 'hides action dropdown for editing the iteration' do
expect(page).not_to have_button('Actions')
end
end
end end
context 'without license' do context 'without license' do
......
...@@ -46,6 +46,10 @@ RSpec.describe 'User views iteration' do ...@@ -46,6 +46,10 @@ RSpec.describe 'User views iteration' do
expect(page).to have_content(closed_issue.title) expect(page).to have_content(closed_issue.title)
expect(page).not_to have_content(other_issue.title) expect(page).not_to have_content(other_issue.title)
end end
it 'hides action dropdown for editing the iteration' do
expect(page).not_to have_button('Actions')
end
end end
end end
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlEmptyState, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui'; import { GlNewDropdown, GlEmptyState, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui';
import IterationReport from 'ee/iterations/components/iteration_report.vue'; import IterationReport from 'ee/iterations/components/iteration_report.vue';
import IterationReportSummary from 'ee/iterations/components/iteration_report_summary.vue'; import IterationReportSummary from 'ee/iterations/components/iteration_report_summary.vue';
import IterationReportTabs from 'ee/iterations/components/iteration_report_tabs.vue'; import IterationReportTabs from 'ee/iterations/components/iteration_report_tabs.vue';
...@@ -108,5 +108,36 @@ describe('Iterations report', () => { ...@@ -108,5 +108,36 @@ describe('Iterations report', () => {
expect(iterationReportTabs.props('iterationId')).toBe(iteration.id); expect(iterationReportTabs.props('iterationId')).toBe(iteration.id);
expect(iterationReportTabs.props('namespaceType')).toBe(Namespace.Group); expect(iterationReportTabs.props('namespaceType')).toBe(Namespace.Group);
}); });
describe('actions dropdown to edit iteration', () => {
describe.each`
description | canEdit | namespaceType | canEditIteration
${'has permissions'} | ${true} | ${Namespace.Group} | ${true}
${'has permissions'} | ${true} | ${Namespace.Project} | ${false}
${'does not have permissions'} | ${false} | ${Namespace.Group} | ${false}
${'does not have permissions'} | ${false} | ${Namespace.Project} | ${false}
`(
'when user $description and they are viewing an iteration within a $namespaceType',
({ canEdit, namespaceType, canEditIteration }) => {
beforeEach(() => {
mountComponent({
props: {
...defaultProps,
canEdit,
namespaceType,
},
});
wrapper.setData({
iteration,
});
});
it(`${canEditIteration ? 'is shown' : 'is hidden'}`, () => {
expect(wrapper.contains(GlNewDropdown)).toBe(canEditIteration);
});
},
);
});
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment