Commit 376caaa2 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'fix/241960-remove-v-html-from-mr-widget-header' into 'master'

Fix 241960, replace v-html with v-safe-html from mr-widget_header.vue

See merge request gitlab-org/gitlab!64837
parents f7ccd64c fcaaf795
<script> <script>
/* eslint-disable vue/no-v-html */
import { import {
GlButton, GlButton,
GlDropdown, GlDropdown,
GlDropdownSectionHeader, GlDropdownSectionHeader,
GlDropdownItem, GlDropdownItem,
GlLink,
GlTooltipDirective, GlTooltipDirective,
GlModalDirective, GlModalDirective,
GlSafeHtmlDirective as SafeHtml,
GlSprintf,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { escape } from 'lodash';
import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility'; import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
import { n__, s__, sprintf } from '~/locale'; import { s__ } from '~/locale';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue'; import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import MrWidgetHowToMergeModal from './mr_widget_how_to_merge_modal.vue'; import MrWidgetHowToMergeModal from './mr_widget_how_to_merge_modal.vue';
...@@ -27,10 +28,13 @@ export default { ...@@ -27,10 +28,13 @@ export default {
GlDropdown, GlDropdown,
GlDropdownSectionHeader, GlDropdownSectionHeader,
GlDropdownItem, GlDropdownItem,
GlLink,
GlSprintf,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
GlModalDirective, GlModalDirective,
SafeHtml,
}, },
props: { props: {
mr: { mr: {
...@@ -42,19 +46,6 @@ export default { ...@@ -42,19 +46,6 @@ export default {
shouldShowCommitsBehindText() { shouldShowCommitsBehindText() {
return this.mr.divergedCommitsCount > 0; return this.mr.divergedCommitsCount > 0;
}, },
commitsBehindText() {
return sprintf(
s__(
'mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch',
),
{
commitsBehindLinkStart: `<a href="${escape(this.mr.targetBranchPath)}">`,
commitsBehind: n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount),
commitsBehindLinkEnd: '</a>',
},
false,
);
},
branchNameClipboardData() { branchNameClipboardData() {
// This supports code in app/assets/javascripts/copy_to_clipboard.js that // This supports code in app/assets/javascripts/copy_to_clipboard.js that
// works around ClipboardJS limitations to allow the context-specific // works around ClipboardJS limitations to allow the context-specific
...@@ -100,10 +91,10 @@ export default { ...@@ -100,10 +91,10 @@ export default {
<strong> <strong>
{{ s__('mrWidget|Request to merge') }} {{ s__('mrWidget|Request to merge') }}
<tooltip-on-truncate <tooltip-on-truncate
v-safe-html="mr.sourceBranchLink"
:title="mr.sourceBranch" :title="mr.sourceBranch"
truncate-target="child" truncate-target="child"
class="label-branch label-truncate js-source-branch" class="label-branch label-truncate js-source-branch"
v-html="mr.sourceBranchLink"
/><clipboard-button /><clipboard-button
data-testid="mr-widget-copy-clipboard" data-testid="mr-widget-copy-clipboard"
:text="branchNameClipboardData" :text="branchNameClipboardData"
...@@ -119,11 +110,15 @@ export default { ...@@ -119,11 +110,15 @@ export default {
<a :href="mr.targetBranchTreePath" class="js-target-branch"> {{ mr.targetBranch }} </a> <a :href="mr.targetBranchTreePath" class="js-target-branch"> {{ mr.targetBranch }} </a>
</tooltip-on-truncate> </tooltip-on-truncate>
</strong> </strong>
<div <div v-if="shouldShowCommitsBehindText" class="diverged-commits-count">
v-if="shouldShowCommitsBehindText" <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
class="diverged-commits-count" <template #link>
v-html="commitsBehindText" <gl-link :href="mr.targetBranchPath">{{
></div> n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
}}</gl-link>
</template>
</gl-sprintf>
</div>
</div> </div>
<div class="branch-actions d-flex"> <div class="branch-actions d-flex">
......
...@@ -38970,7 +38970,7 @@ msgstr "" ...@@ -38970,7 +38970,7 @@ msgstr ""
msgid "mrWidget|The source branch has been deleted" msgid "mrWidget|The source branch has been deleted"
msgstr "" msgstr ""
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch" msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "" msgstr ""
msgid "mrWidget|The source branch is being deleted" msgid "mrWidget|The source branch is being deleted"
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount, mount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import Header from '~/vue_merge_request_widget/components/mr_widget_header.vue'; import Header from '~/vue_merge_request_widget/components/mr_widget_header.vue';
...@@ -26,6 +26,15 @@ describe('MRWidgetHeader', () => { ...@@ -26,6 +26,15 @@ describe('MRWidgetHeader', () => {
expect(downloadPlainDiffEl.attributes('href')).toBe('/mr/plainDiffPath'); expect(downloadPlainDiffEl.attributes('href')).toBe('/mr/plainDiffPath');
}; };
const commonMrProps = {
divergedCommitsCount: 1,
sourceBranch: 'mr-widget-refactor',
sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
targetBranch: 'main',
targetBranchPath: '/foo/bar/main',
statusPath: 'abc',
};
describe('computed', () => { describe('computed', () => {
describe('shouldShowCommitsBehindText', () => { describe('shouldShowCommitsBehindText', () => {
it('return true when there are divergedCommitsCount', () => { it('return true when there are divergedCommitsCount', () => {
...@@ -59,36 +68,28 @@ describe('MRWidgetHeader', () => { ...@@ -59,36 +68,28 @@ describe('MRWidgetHeader', () => {
describe('commitsBehindText', () => { describe('commitsBehindText', () => {
it('returns singular when there is one commit', () => { it('returns singular when there is one commit', () => {
createComponent({ wrapper = mount(Header, {
mr: { propsData: {
divergedCommitsCount: 1, mr: commonMrProps,
sourceBranch: 'mr-widget-refactor',
sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
targetBranch: 'main',
targetBranchPath: '/foo/bar/main',
statusPath: 'abc',
}, },
}); });
expect(wrapper.vm.commitsBehindText).toBe( expect(wrapper.find('.diverged-commits-count').element.innerHTML).toBe(
'The source branch is <a href="/foo/bar/main">1 commit behind</a> the target branch', 'The source branch is <a href="/foo/bar/main" class="gl-link">1 commit behind</a> the target branch',
); );
}); });
it('returns plural when there is more than one commit', () => { it('returns plural when there is more than one commit', () => {
createComponent({ wrapper = mount(Header, {
propsData: {
mr: { mr: {
...commonMrProps,
divergedCommitsCount: 2, divergedCommitsCount: 2,
sourceBranch: 'mr-widget-refactor', },
sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
targetBranch: 'main',
targetBranchPath: '/foo/bar/main',
statusPath: 'abc',
}, },
}); });
expect(wrapper.find('.diverged-commits-count').element.innerHTML).toBe(
expect(wrapper.vm.commitsBehindText).toBe( 'The source branch is <a href="/foo/bar/main" class="gl-link">2 commits behind</a> the target branch',
'The source branch is <a href="/foo/bar/main">2 commits behind</a> the target branch',
); );
}); });
}); });
...@@ -273,19 +274,18 @@ describe('MRWidgetHeader', () => { ...@@ -273,19 +274,18 @@ describe('MRWidgetHeader', () => {
describe('with diverged commits', () => { describe('with diverged commits', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ wrapper = mount(Header, {
propsData: {
mr: { mr: {
...commonMrProps,
divergedCommitsCount: 12, divergedCommitsCount: 12,
sourceBranch: 'mr-widget-refactor',
sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>',
sourceBranchRemoved: false, sourceBranchRemoved: false,
targetBranchPath: 'foo/bar/commits-path', targetBranchPath: 'foo/bar/commits-path',
targetBranchTreePath: 'foo/bar/tree/path', targetBranchTreePath: 'foo/bar/tree/path',
targetBranch: 'main',
isOpen: true, isOpen: true,
emailPatchesPath: '/mr/email-patches', emailPatchesPath: '/mr/email-patches',
plainDiffPath: '/mr/plainDiffPath', plainDiffPath: '/mr/plainDiffPath',
statusPath: 'abc', },
}, },
}); });
}); });
......
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