Commit 46614d75 authored by Nick Thomas's avatar Nick Thomas

Merge branch '7287-epic-references' into 'master'

Support short reference to epics from project entities

Closes #7287

See merge request gitlab-org/gitlab-ee!7475
parents 1afc21c9 78347c0e
......@@ -42,7 +42,7 @@ discussions, and descriptions:
| `/remove_due_date` | Remove due date | ✓ | |
| `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | |
| `/clear_weight` | Clears weight **[STARTER]** | ✓ | |
| `/epic <group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
| `/epic <&epic &#124; group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
| `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | |
| `/confidential` | Make confidential | ✓ | |
| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ |
......
......@@ -194,7 +194,7 @@ module EE
def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}"
return reference unless cross_reference?(from) || full
return reference unless (cross_reference?(from) && !group.projects.include?(from)) || full
"#{group.full_path}#{reference}"
end
......
......@@ -55,7 +55,7 @@ module EE
issuable.project.group&.feature_available?(:epics) &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
params '<group&epic | Epic URL>'
params '<&epic | group&epic | Epic URL>'
command :epic do |epic_param|
@updates[:epic] = extract_epic(epic_param)
end
......
---
title: Support short reference to epics from project entities
merge_request: 7475
author:
type: changed
......@@ -6,31 +6,50 @@ describe 'Referencing Epics', :js do
let(:epic) { create(:epic, group: group) }
let(:project) { create(:project, :public) }
let(:reference) { epic.to_reference(full: true) }
let(:full_reference) { epic.to_reference(full: true) }
context 'reference on an issue' do
let(:issue) { create(:issue, project: project, description: "Check #{reference}") }
before do
stub_licensed_features(epics: true)
sign_in(user)
end
context 'when referencing epics from the direct parent' do
let(:epic2) { create(:epic, group: group) }
let(:short_reference) { epic2.to_reference }
let(:text) { "Check #{full_reference} #{short_reference}" }
let(:child_project) { create(:project, :public, group: group) }
let(:issue) { create(:issue, project: child_project, description: text) }
it 'displays link to the reference' do
visit project_issue_path(child_project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(epic.to_reference, href: group_epic_path(group, epic))
expect(page).to have_link(short_reference, href: group_epic_path(group, epic2))
end
end
end
context 'when referencing an epic from another group' do
let(:text) { "Check #{full_reference}" }
let(:issue) { create(:issue, project: project, description: text) }
context 'when non group member displays the issue' do
context 'when referenced epic is in a public group' do
it 'displays link to the reference' do
visit project_issue_path(project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic))
expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end
end
end
context 'when referenced epic is in a private group' do
before do
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it 'does not display link to the reference' do
......@@ -47,14 +66,15 @@ describe 'Referencing Epics', :js do
context 'when referenced epic is in a private group' do
before do
group.add_developer(user)
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it 'displays link to the reference' do
visit project_issue_path(project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic))
expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end
end
end
end
......
......@@ -470,6 +470,10 @@ describe Epic do
describe '#to_reference' do
let(:group) { create(:group, path: 'group-a') }
let(:subgroup) { create(:group) }
let(:group_project) { create(:project, group: group) }
let(:subgroup_project) { create(:project, group: subgroup) }
let(:other_project) { create(:project) }
let(:epic) { create(:epic, iid: 1, group: group) }
context 'when nil argument' do
......@@ -478,23 +482,42 @@ describe Epic do
end
end
context 'when group argument equals epic group' do
context 'when from argument equals epic group' do
it 'returns epic id' do
expect(epic.to_reference(epic.group)).to eq('&1')
end
end
context 'when group argument differs from epic group' do
context 'when from argument is a group different from epic group' do
it 'returns complete path to the epic' do
expect(epic.to_reference(create(:group))).to eq('group-a&1')
end
end
context 'when from argument is a project under the epic group' do
it 'returns epic id' do
expect(epic.to_reference(group_project)).to eq('&1')
end
end
context 'when from argument is a project under the epic subgroup' do
it 'returns complete path to the epic' do
expect(epic.to_reference(subgroup_project)).to eq('group-a&1')
end
end
context 'when from argument is a project in another group' do
it 'returns complete path to the epic' do
expect(epic.to_reference(other_project)).to eq('group-a&1')
end
end
context 'when full is true' do
it 'returns complete path to the epic' do
expect(epic.to_reference(full: true)).to eq('group-a&1')
expect(epic.to_reference(epic.group, full: true)).to eq('group-a&1')
expect(epic.to_reference(group, full: true)).to eq('group-a&1')
expect(epic.to_reference(group_project, full: true)).to eq('group-a&1')
end
end
end
......
......@@ -11,6 +11,12 @@ module Banzai
def self.object_class
Epic
end
private
def group
context[:group] || context[:project]&.group
end
end
end
end
......@@ -331,11 +331,12 @@ describe CacheMarkdownField do
end
context 'with a project' do
let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: :project_value) }
let(:project) { create(:project, group: create(:group)) }
let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: project) }
it 'sets the project in the context' do
is_expected.to have_key(:project)
expect(context[:project]).to eq(:project_value)
expect(context[:project]).to eq(project)
end
it 'invalidates the cache when project changes' do
......
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