diff --git a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue new file mode 100644 index 00000000000..e413398696a --- /dev/null +++ b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue @@ -0,0 +1,34 @@ + + + diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 2d6fd8b116f..3894dc8c677 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -25,6 +25,7 @@ import noteable from '../mixins/noteable'; import resolvable from '../mixins/resolvable'; import discussionNavigation from '../mixins/discussion_navigation'; import ReplyPlaceholder from './discussion_reply_placeholder.vue'; +import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue'; import jumpToNextDiscussionButton from './discussion_jump_to_next_button.vue'; import eventHub from '../event_hub'; @@ -44,6 +45,7 @@ export default { ReplyPlaceholder, placeholderNote, placeholderSystemNote, + ResolveWithIssueButton, systemNote, TimelineEntryItem, }, @@ -234,6 +236,9 @@ export default { url: this.discussion.discussion_path, }; }, + resolveWithIssuePath() { + return !this.discussionResolved && this.discussion.resolve_with_issue_path; + }, }, watch: { isReplying() { @@ -487,16 +492,10 @@ Please check your network connection and try again.`; class="btn-group discussion-actions ml-sm-2" role="group" > -
- - - -
+ { + let wrapper; + const url = `${TEST_HOST}/hello-world/`; + + beforeEach(() => { + wrapper = shallowMount(ResolveWithIssueButton, { + localVue, + sync: false, + propsData: { + url, + }, + }); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('it should have a link with the provided link property as href', () => { + const button = wrapper.find(GlButton); + + expect(button.attributes().href).toBe(url); + }); +}); diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js index 2eae22e095f..2b93fb9fb45 100644 --- a/spec/javascripts/notes/components/noteable_discussion_spec.js +++ b/spec/javascripts/notes/components/noteable_discussion_spec.js @@ -2,6 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import createStore from '~/notes/stores'; import noteableDiscussion from '~/notes/components/noteable_discussion.vue'; import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; +import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; import '~/behaviors/markdown/render_gfm'; import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data'; import mockDiffFile from '../../diffs/mock_data/diff_file'; @@ -238,4 +239,42 @@ describe('noteable_discussion component', () => { }); }); }); + + describe('for resolved discussion', () => { + beforeEach(() => { + const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0]; + wrapper.setProps({ discussion }); + }); + + it('does not display a button to resolve with issue', () => { + const button = wrapper.find(ResolveWithIssueButton); + + expect(button.exists()).toBe(false); + }); + }); + + describe('for unresolved discussion', () => { + beforeEach(done => { + const discussion = { + ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0], + expanded: true, + }; + discussion.notes = discussion.notes.map(note => ({ + ...note, + resolved: false, + })); + + wrapper.setProps({ discussion }); + wrapper.vm + .$nextTick() + .then(done) + .catch(done.fail); + }); + + it('displays a button to resolve with issue', () => { + const button = wrapper.find(ResolveWithIssueButton); + + expect(button.exists()).toBe(true); + }); + }); });