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);
+ });
+ });
});