diff options
19 files changed, 248 insertions, 78 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index bec71a83945..dee72930a28 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -83,7 +83,6 @@ schedule:review-build-cng: <<: *review-schedules-only <<: *review-build-cng-base - .review-deploy-base: &review-deploy-base <<: *review-base allow_failure: true @@ -176,6 +175,7 @@ review-performance: <<: *review-performance-base review-stop: + <<: *review-base extends: .single-script-job-dedicated-runner image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base allow_failure: true diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index c81e754df4c..f1e26cdfa21 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -461,7 +461,10 @@ class GfmAutoComplete { // We can ignore this for quick actions because they are processed // before Markdown. if (!this.setting.skipMarkdownCharacterTest) { - withoutAt = withoutAt.replace(/([~\-_*`])/g, '\\$&'); + withoutAt = withoutAt + .replace(/(~~|`|\*)/g, '\\$1') + .replace(/(\b)(_+)/g, '$1\\$2') // only escape underscores at the start + .replace(/(_+)(\b)/g, '\\$1$2'); // or end of words } return `${at}${withoutAt}`; diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue new file mode 100644 index 00000000000..22cca756ef6 --- /dev/null +++ b/app/assets/javascripts/notes/components/discussion_actions.vue @@ -0,0 +1,58 @@ +<script> +import ReplyPlaceholder from './discussion_reply_placeholder.vue'; +import ResolveDiscussionButton from './discussion_resolve_button.vue'; +import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue'; +import JumpToNextDiscussionButton from './discussion_jump_to_next_button.vue'; + +export default { + name: 'DiscussionActions', + components: { + ReplyPlaceholder, + ResolveDiscussionButton, + ResolveWithIssueButton, + JumpToNextDiscussionButton, + }, + props: { + discussion: { + type: Object, + required: true, + }, + isResolving: { + type: Boolean, + required: true, + }, + resolveButtonTitle: { + type: String, + required: true, + }, + resolveWithIssuePath: { + type: String, + required: false, + default: '', + }, + shouldShowJumpToNextDiscussion: { + type: Boolean, + required: true, + }, + }, +}; +</script> + +<template> + <div class="discussion-with-resolve-btn"> + <reply-placeholder class="qa-discussion-reply" @onClick="$emit('showReplyForm')" /> + <resolve-discussion-button + v-if="discussion.resolvable" + :is-resolving="isResolving" + :button-title="resolveButtonTitle" + @onClick="$emit('resolve')" + /> + <div v-if="discussion.resolvable" class="btn-group discussion-actions ml-sm-2" role="group"> + <resolve-with-issue-button v-if="resolveWithIssuePath" :url="resolveWithIssuePath" /> + <jump-to-next-discussion-button + v-if="shouldShowJumpToNextDiscussion" + @onClick="$emit('jumpToNextDiscussion')" + /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index a3d664a738f..89563711bcd 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -14,7 +14,6 @@ import { SYSTEM_NOTE } from '../constants'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import noteableNote from './noteable_note.vue'; import noteHeader from './note_header.vue'; -import resolveDiscussionButton from './discussion_resolve_button.vue'; import toggleRepliesWidget from './toggle_replies_widget.vue'; import noteSignedOutWidget from './note_signed_out_widget.vue'; import noteEditedText from './note_edited_text.vue'; @@ -25,10 +24,8 @@ import placeholderSystemNote from '../../vue_shared/components/notes/placeholder 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'; +import DiscussionActions from './discussion_actions.vue'; export default { name: 'NoteableDiscussion', @@ -40,16 +37,13 @@ export default { noteSignedOutWidget, noteEditedText, noteForm, - resolveDiscussionButton, - jumpToNextDiscussionButton, toggleRepliesWidget, - ReplyPlaceholder, placeholderNote, placeholderSystemNote, - ResolveWithIssueButton, systemNote, DraftNote: () => import('ee_component/batch_comments/components/draft_note.vue'), TimelineEntryItem, + DiscussionActions, }, directives: { GlTooltip: GlTooltipDirective, @@ -465,31 +459,17 @@ Please check your network connection and try again.`; :class="{ 'is-replying': isReplying }" class="discussion-reply-holder" > - <template v-if="!isReplying && canReply"> - <div class="discussion-with-resolve-btn"> - <reply-placeholder class="qa-discussion-reply" @onClick="showReplyForm" /> - <resolve-discussion-button - v-if="discussion.resolvable" - :is-resolving="isResolving" - :button-title="resolveButtonTitle" - @onClick="resolveHandler" - /> - <div - v-if="discussion.resolvable" - class="btn-group discussion-actions ml-sm-2" - role="group" - > - <resolve-with-issue-button - v-if="resolveWithIssuePath" - :url="resolveWithIssuePath" - /> - <jump-to-next-discussion-button - v-if="shouldShowJumpToNextDiscussion" - @onClick="jumpToNextDiscussion" - /> - </div> - </div> - </template> + <discussion-actions + v-if="!isReplying && canReply" + :discussion="discussion" + :is-resolving="isResolving" + :resolve-button-title="resolveButtonTitle" + :resolve-with-issue-path="resolveWithIssuePath" + :should-show-jump-to-next-discussion="shouldShowJumpToNextDiscussion" + @showReplyForm="showReplyForm" + @resolve="resolveHandler" + @jumpToNextDiscussion="jumpToNextDiscussion" + /> <note-form v-if="isReplying" ref="noteForm" diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss index 42ede599bc6..9775c329922 100644 --- a/app/assets/stylesheets/components/dashboard_skeleton.scss +++ b/app/assets/stylesheets/components/dashboard_skeleton.scss @@ -8,10 +8,6 @@ &-warning { background-color: $orange-100; } - - &-failed { - background-color: $red-100; - } } &-body { @@ -36,10 +32,6 @@ border-radius: $gl-padding; height: $gl-padding-32; - &-failed { - background-color: $red-100; - } - &-arrow { color: $gray-300; } @@ -56,6 +48,13 @@ } } + &-header, + &-footer { + &-failed { + background-color: $red-100; + } + } + &-skeleton-info { border-radius: $gl-padding; height: $gl-padding; diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 2c95ac6dbb3..4bf1d8702af 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -77,7 +77,7 @@ = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue-edited-ago js-issue-edited-ago') - #js-related-merge-requests{ data: { endpoint: api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid), project_namespace: @project.namespace.path, project_path: @project.path } } + #js-related-merge-requests{ data: { endpoint: expose_url(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } } - if can?(current_user, :download_code, @project) #related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } } diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index ff7c36c2d5b..95027634de2 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -48,7 +48,12 @@ = form_for @project, html: { class: 'new_project' } do |f| = render 'new_project_fields', f: f, project_name_id: "blank-project-name" - .tab-pane.no-padding{ id: 'create-from-template-pane', class: active_when(active_tab == 'template'), role: 'tabpanel' } + #create-from-template-pane.tab-pane.px-0.pb-0{ class: active_when(active_tab == 'template'), role: 'tabpanel' } + .card-slim.m-4.p-4 + %div + - contributing_templates_url = 'https://gitlab.com/gitlab-org/project-templates/contributing' + - link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: contributing_templates_url } + = _('Learn how to %{link_start}contribute to the built-in templates%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } = form_for @project, html: { class: 'new_project' } do |f| .project-template .form-group diff --git a/changelogs/unreleased/58293-extract-discussion-actions.yml b/changelogs/unreleased/58293-extract-discussion-actions.yml new file mode 100644 index 00000000000..2ca4716a6de --- /dev/null +++ b/changelogs/unreleased/58293-extract-discussion-actions.yml @@ -0,0 +1,5 @@ +--- +title: Extract DiscussionActions component from NoteableDiscussion +merge_request: 27227 +author: +type: other diff --git a/changelogs/unreleased/markdown-autocomplete-escaping.yml b/changelogs/unreleased/markdown-autocomplete-escaping.yml new file mode 100644 index 00000000000..0ea034b14ee --- /dev/null +++ b/changelogs/unreleased/markdown-autocomplete-escaping.yml @@ -0,0 +1,5 @@ +--- +title: Only escape Markdown emphasis characters in autocomplete when necessary +merge_request: 27457 +author: +type: changed diff --git a/changelogs/unreleased/rename_auto_deploy_app_links.yml b/changelogs/unreleased/rename_auto_deploy_app_links.yml new file mode 100644 index 00000000000..c56b5fb5e5c --- /dev/null +++ b/changelogs/unreleased/rename_auto_deploy_app_links.yml @@ -0,0 +1,5 @@ +--- +title: Move location of charts/auto-deploy-app -> gitlab-org/charts/auto-deploy-app +merge_request: 27477 +author: +type: changed diff --git a/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml b/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml new file mode 100644 index 00000000000..b868758dcd2 --- /dev/null +++ b/changelogs/unreleased/xanf-gitlab-ce-add-template-link.yml @@ -0,0 +1,5 @@ +--- +title: Add instructions on how to contribute a Built-In template for project +merge_request: 26976 +author: +type: other diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md index 2de751c9e62..6a03ab910fc 100644 --- a/doc/ci/merge_request_pipelines/index.md +++ b/doc/ci/merge_request_pipelines/index.md @@ -69,7 +69,7 @@ when a merge request was created or updated. For example: ## Combined ref pipelines **[PREMIUM]** -> [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7380) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10. It's possible for your source and target branches to diverge, which can result in the scenario that source branch's pipeline was green, the target's pipeline was green, diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 1d517a65ce2..0ab9406c681 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -460,7 +460,7 @@ for example after the merge request is merged, the Review App will automatically be deleted. Review apps are deployed using the -[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with +[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with Helm. The app will be deployed into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables) for the environment. @@ -528,7 +528,7 @@ You can make use of [environment variables](#environment-variables) to automatic scale your pod replicas. Apps are deployed using the -[auto-deploy-app](https://gitlab.com/charts/auto-deploy-app) chart with +[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with Helm. The app will be deployed into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables) for the environment. @@ -667,7 +667,7 @@ repo or by specifying a project variable: - **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml` file in it, Auto DevOps will detect the chart and use it instead of the [default - one](https://gitlab.com/charts/auto-deploy-app). + one](https://gitlab.com/gitlab-org/charts/auto-deploy-app). This can be a great way to control exactly how your application is deployed. - **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables) `AUTO_DEVOPS_CHART` with the URL of a custom chart to use or create two project variables `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository and `AUTO_DEVOPS_CHART` with the path to the chart. @@ -735,7 +735,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac | **Variable** | **Description** | | ------------ | --------------- | | `AUTO_DEVOPS_DOMAIN` | The [Auto DevOps domain](#auto-devops-base-domain). By default, set automatically by the [Auto DevOps setting](#enablingdisabling-auto-devops). This variable is deprecated and [is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-ce/issues/56959). Use `KUBE_INGRESS_BASE_DOMAIN` instead. | -| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/charts/auto-deploy-app). | +| `AUTO_DEVOPS_CHART` | The Helm Chart used to deploy your apps; defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/charts/auto-deploy-app). | | `AUTO_DEVOPS_CHART_REPOSITORY` | The Helm Chart repository used to search for charts; defaults to `https://charts.gitlab.io`. | | `REPLICAS` | The number of replicas to deploy; defaults to 1. | | `PRODUCTION_REPLICAS` | The number of replicas to deploy in the production environment. This takes precedence over `REPLICAS`; defaults to 1. | diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index bf41fdecd10..c7e8bb5b33b 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -348,19 +348,23 @@ Custom commit messages will be introduced by > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/53310) in GitLab 11.10. -Reviewers can also suggest changes to -multiple lines with a single suggestion within Merge Request diff discussions. +Reviewers can also suggest changes to multiple lines with a single suggestion +within Merge Request diff discussions by adjusting the range offsets. The +offsets are relative to the position of the diff discussion, and specify the +range to be replaced by the suggestion when it is applied. ![Multi-line suggestion syntax](img/multi-line-suggestion-syntax.png) -In the example above, the suggestion covers three lines above and four lines below the commented diff line. -It'd change from 3 lines _above_ to 4 lines _below_ the commented Diff line. +In the example above, the suggestion covers three lines above and four lines +below the commented line. When applied, it would replace from 3 lines _above_ +to 4 lines _below_ the commented line, with the suggested change. ![Multi-line suggestion preview](img/multi-line-suggestion-preview.png) NOTE: **Note:** -Suggestions covering multiple lines are limited to 100 lines _above_ and 100 lines _below_ -the commented diff line, allowing up to 200 changed lines per suggestion. +Suggestions covering multiple lines are limited to 100 lines _above_ and 100 +lines _below_ the commented diff line, allowing up to 200 changed lines per +suggestion. ## Start a discussion by replying to a standard comment diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index 5b7e9ef906f..dfbed0ec95f 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -158,21 +158,6 @@ Follow these steps to deploy a function using the Node.js runtime to your Knativ description: "node.js runtime function" environment: MY_FUNCTION: echo-js - - echo-rb: - handler: MyEcho.my_function - source: ./echo-rb - runtime: https://gitlab.com/gitlab-org/serverless/runtimes/ruby - description: "Ruby runtime function" - environment: - MY_FUNCTION: echo-rb - - echo-docker: - handler: echo-docker - source: ./echo-docker - description: "Dockerfile runtime function" - environment: - MY_FUNCTION: echo-docker ``` Explanation of the fields used above: diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0d6cb4c85b5..6b1d9e268c5 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5260,6 +5260,9 @@ msgstr "" msgid "Lead" msgstr "" +msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}" +msgstr "" + msgid "Learn more" msgstr "" diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index f5add6bc9b5..07e191f1c9b 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -15,7 +15,7 @@ module QA element :reply_comment_button end - base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do + base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do element :discussion_reply end diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js index ed12af925f1..841aff0d7ff 100644 --- a/spec/frontend/gfm_auto_complete_spec.js +++ b/spec/frontend/gfm_auto_complete_spec.js @@ -94,7 +94,7 @@ describe('GfmAutoComplete', () => { }); it('should quote if value contains any non-alphanumeric characters', () => { - expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label\\-20"'); + expect(beforeInsert(atwhoInstance, '~label-20')).toBe('~"label-20"'); expect(beforeInsert(atwhoInstance, '~label 20')).toBe('~"label 20"'); }); @@ -102,12 +102,21 @@ describe('GfmAutoComplete', () => { expect(beforeInsert(atwhoInstance, '~1234')).toBe('~"1234"'); }); - it('should escape Markdown emphasis characters, except in the first character', () => { - expect(beforeInsert(atwhoInstance, '@_group')).toEqual('@\\_group'); - expect(beforeInsert(atwhoInstance, '~_bug')).toEqual('~\\_bug'); + it('escapes Markdown strikethroughs when needed', () => { + expect(beforeInsert(atwhoInstance, '~a~bug')).toEqual('~"a~bug"'); + expect(beforeInsert(atwhoInstance, '~a~~bug~~')).toEqual('~"a\\~~bug\\~~"'); + }); + + it('escapes Markdown emphasis when needed', () => { + expect(beforeInsert(atwhoInstance, '~a_bug_')).toEqual('~a_bug\\_'); + expect(beforeInsert(atwhoInstance, '~a _bug_')).toEqual('~"a \\_bug\\_"'); + expect(beforeInsert(atwhoInstance, '~a*bug*')).toEqual('~"a\\*bug\\*"'); + expect(beforeInsert(atwhoInstance, '~a *bug*')).toEqual('~"a \\*bug\\*"'); + }); + + it('escapes Markdown code spans when needed', () => { + expect(beforeInsert(atwhoInstance, '~a`bug`')).toEqual('~"a\\`bug\\`"'); expect(beforeInsert(atwhoInstance, '~a `bug`')).toEqual('~"a \\`bug\\`"'); - expect(beforeInsert(atwhoInstance, '~a ~bug')).toEqual('~"a \\~bug"'); - expect(beforeInsert(atwhoInstance, '~a **bug')).toEqual('~"a \\*\\*bug"'); }); }); diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js new file mode 100644 index 00000000000..0a52c81571e --- /dev/null +++ b/spec/frontend/notes/components/discussion_actions_spec.js @@ -0,0 +1,104 @@ +import createStore from '~/notes/stores'; +import { shallowMount, mount, createLocalVue } from '@vue/test-utils'; +import { discussionMock } from '../../../javascripts/notes/mock_data'; +import DiscussionActions from '~/notes/components/discussion_actions.vue'; +import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; +import ResolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue'; +import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue'; +import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue'; + +describe('DiscussionActions', () => { + let wrapper; + const createComponentFactory = (shallow = true) => props => { + const localVue = createLocalVue(); + const store = createStore(); + const mountFn = shallow ? shallowMount : mount; + + wrapper = mountFn(DiscussionActions, { + localVue, + store, + propsData: { + discussion: discussionMock, + isResolving: false, + resolveButtonTitle: 'Resolve discussion', + resolveWithIssuePath: '/some/issue/path', + shouldShowJumpToNextDiscussion: true, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + describe('rendering', () => { + const createComponent = createComponentFactory(); + + it('renders reply placeholder, resolve discussion button, resolve with issue button and jump to next discussion button', () => { + createComponent(); + expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true); + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true); + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(true); + }); + + it('only renders reply placholder if disccusion is not resolvable', () => { + const discussion = { ...discussionMock }; + discussion.resolvable = false; + createComponent({ discussion }); + + expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true); + expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false); + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); + }); + + it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => { + createComponent({ resolveWithIssuePath: '' }); + + expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false); + }); + + it('does not render jump to next discussion button if shouldShowJumpToNextDiscussion is false', () => { + createComponent({ shouldShowJumpToNextDiscussion: false }); + + expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false); + }); + }); + + describe('events handling', () => { + const createComponent = createComponentFactory(false); + + beforeEach(() => { + createComponent(); + }); + + it('emits showReplyForm event when clicking on reply placeholder', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(ReplyPlaceholder) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm'); + }); + + it('emits resolve event when clicking on resolve button', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(ResolveDiscussionButton) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve'); + }); + + it('emits jumpToNextDiscussion event when clicking on jump to next discussion button', () => { + jest.spyOn(wrapper.vm, '$emit'); + wrapper + .find(JumpToNextDiscussionButton) + .find('button') + .trigger('click'); + expect(wrapper.vm.$emit).toHaveBeenCalledWith('jumpToNextDiscussion'); + }); + }); +}); |