Commit ed092037 authored by Frédéric Caplette's avatar Frédéric Caplette Committed by Miguel Rincon

Update merge train helper text

We update the merge train helper text
and we move it right under the button for
more clarity. This mean we had to move
the helper text component from the mr-widget-options
to the ready-to-merge component and update the
tests accordingly.
parent 75ce65df
......@@ -15,7 +15,16 @@ import SquashBeforeMerge from './squash_before_merge.vue';
import CommitsHeader from './commits_header.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
import { AUTO_MERGE_STRATEGIES } from '../../constants';
import { AUTO_MERGE_STRATEGIES, DANGER, INFO, WARNING } from '../../constants';
const PIPELINE_RUNNING_STATE = 'running';
const PIPELINE_FAILED_STATE = 'failed';
const PIPELINE_PENDING_STATE = 'pending';
const PIPELINE_SUCCESS_STATE = 'success';
const MERGE_FAILED_STATUS = 'failed';
const MERGE_SUCCESS_STATUS = 'success';
const MERGE_HOOK_VALIDATION_ERROR_STATUS = 'hook_validation_error';
export default {
name: 'ReadyToMerge',
......@@ -29,6 +38,8 @@ export default {
GlSprintf,
GlLink,
GlDeprecatedButton,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
import(
'ee_component/vue_merge_request_widget/components/merge_immediately_confirmation_dialog.vue'
......@@ -60,35 +71,45 @@ export default {
const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr;
if ((hasCI && !ciStatus) || this.hasPipelineMustSucceedConflict) {
return 'failed';
} else if (this.isAutoMergeAvailable) {
return 'pending';
} else if (!pipeline) {
return 'success';
} else if (isPipelineFailed) {
return 'failed';
return PIPELINE_FAILED_STATE;
}
if (this.isAutoMergeAvailable) {
return PIPELINE_PENDING_STATE;
}
if (pipeline && isPipelineFailed) {
return PIPELINE_FAILED_STATE;
}
return 'success';
return PIPELINE_SUCCESS_STATE;
},
mergeButtonVariant() {
if (this.status === 'failed') {
return 'danger';
} else if (this.status === 'pending') {
return 'info';
if (this.status === PIPELINE_FAILED_STATE) {
return DANGER;
}
return 'success';
if (this.status === PIPELINE_PENDING_STATE) {
return INFO;
}
return PIPELINE_SUCCESS_STATE;
},
iconClass() {
if (this.shouldRenderMergeTrainHelperText && !this.mr.preventMerge) {
return PIPELINE_RUNNING_STATE;
}
if (
this.status === 'failed' ||
this.status === PIPELINE_FAILED_STATE ||
!this.commitMessage.length ||
!this.mr.isMergeAllowed ||
this.mr.preventMerge
) {
return 'warning';
return WARNING;
}
return 'success';
return PIPELINE_SUCCESS_STATE;
},
mergeButtonText() {
if (this.isMergingImmediately) {
......@@ -167,11 +188,13 @@ export default {
.merge(options)
.then(res => res.data)
.then(data => {
const hasError = data.status === 'failed' || data.status === 'hook_validation_error';
const hasError =
data.status === MERGE_FAILED_STATUS ||
data.status === MERGE_HOOK_VALIDATION_ERROR_STATUS;
if (AUTO_MERGE_STRATEGIES.includes(data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
} else if (data.status === 'success') {
} else if (data.status === MERGE_SUCCESS_STATUS) {
this.initiateMergePolling();
} else if (hasError) {
eventHub.$emit('FailedToMerge', data.merge_error);
......@@ -269,7 +292,7 @@ export default {
<template>
<div>
<div class="mr-widget-body media">
<div class="mr-widget-body media" :class="{ 'gl-pb-3': shouldRenderMergeTrainHelperText }">
<status-icon :status="iconClass" />
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
......@@ -358,6 +381,7 @@ export default {
<div
v-if="hasPipelineMustSucceedConflict"
class="gl-display-flex gl-align-items-center"
data-testid="pipeline-succeed-conflict"
>
<gl-sprintf :message="pipelineMustSucceedConflictText" />
<gl-link
......@@ -379,6 +403,13 @@ export default {
</div>
</div>
</div>
<merge-train-helper-text
v-if="shouldRenderMergeTrainHelperText"
:pipeline-id="mr.pipeline.id"
:pipeline-link="mr.pipeline.path"
:merge-train-length="mr.mergeTrainsCount"
:merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
/>
<template v-if="shouldShowMergeControls">
<div v-if="mr.ffOnlyEnabled" class="mr-fast-forward-message">
{{ __('Fast-forward merge without a merge commit') }}
......
......@@ -3,6 +3,7 @@ import { s__ } from '~/locale';
export const SUCCESS = 'success';
export const WARNING = 'warning';
export const DANGER = 'danger';
export const INFO = 'info';
export const WARNING_MESSAGE_CLASS = 'warning_message';
export const DANGER_MESSAGE_CLASS = 'danger_message';
......
<script>
import { escape } from 'lodash';
import { GlLink } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
name: 'MergeTrainHelperText',
components: {
GlLink,
GlSprintf,
},
props: {
pipelineId: {
......@@ -27,26 +27,13 @@ export default {
},
},
computed: {
message() {
const text =
this.mergeTrainLength === 0
helperMessage() {
return this.mergeTrainLength === 0
? s__(
'mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds.',
'mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds.',
)
: s__(
'mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds.',
);
const sanitizedPipelineLink = escape(this.pipelineLink);
return sprintf(
text,
{
pipelineId: this.pipelineId,
linkStart: `<a class="js-pipeline-link" href="${sanitizedPipelineLink}">`,
linkEnd: '</a>',
},
false,
'mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds.',
);
},
},
......@@ -54,15 +41,21 @@ export default {
</script>
<template>
<section class="js-merge-train-helper-text mr-widget-help border-top">
<span v-html="message"></span>
<section class="js-merge-train-helper-text gl-px-5 gl-pb-5">
<div class="gl-pl-7">
<gl-sprintf :message="helperMessage">
<template #pipelineLink>
<gl-link data-testid="pipeline-link" :href="pipelineLink">#{{ pipelineId }}</gl-link>
</template>
</gl-sprintf>
<gl-link
:href="mergeTrainWhenPipelineSucceedsDocsPath"
target="_blank"
rel="noopener noreferrer"
class="js-documentation-link"
data-testid="documentation-link"
>
{{ s__('mrWidget|More information') }}
</gl-link>
</div>
</section>
</template>
import { isNumber, isString } from 'lodash';
import { MTWPS_MERGE_STRATEGY, MT_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
import { __ } from '~/locale';
import base from '~/vue_merge_request_widget/mixins/ready_to_merge';
......@@ -48,6 +49,15 @@ export default {
}
return __('Merge when pipeline succeeds');
},
shouldRenderMergeTrainHelperText() {
return (
this.mr.pipeline &&
isNumber(this.mr.pipeline.id) &&
isString(this.mr.pipeline.path) &&
this.mr.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY &&
!this.mr.autoMergeEnabled
);
},
shouldShowMergeImmediatelyDropdown() {
if (this.mr.preferredAutoMergeStrategy === MT_MERGE_STRATEGY) {
return true;
......
<script>
import { isNumber, isString } from 'lodash';
import GroupedSecurityReportsApp from 'ee/vue_shared/security_reports/grouped_security_reports_app.vue';
import GroupedMetricsReportsApp from 'ee/vue_shared/metrics_reports/grouped_metrics_reports_app.vue';
import reportsMixin from 'ee/vue_shared/security_reports/mixins/reports_mixin';
......@@ -12,12 +11,9 @@ import { s__, __, sprintf } from '~/locale';
import CEWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import MrWidgetGeoSecondaryNode from './components/states/mr_widget_secondary_geo_node.vue';
import MrWidgetPolicyViolation from './components/states/mr_widget_policy_violation.vue';
import MergeTrainHelperText from './components/merge_train_helper_text.vue';
import { MTWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
export default {
components: {
MergeTrainHelperText,
MrWidgetLicenses,
MrWidgetGeoSecondaryNode,
MrWidgetPolicyViolation,
......@@ -156,16 +152,6 @@ export default {
this.loadingLoadPerformanceFailed,
);
},
shouldRenderMergeTrainHelperText() {
return (
this.mr.pipeline &&
isNumber(this.mr.pipeline.id) &&
isString(this.mr.pipeline.path) &&
this.mr.preferredAutoMergeStrategy === MTWPS_MERGE_STRATEGY &&
!this.mr.autoMergeEnabled
);
},
licensesApiPath() {
return gl?.mrWidgetData?.license_scanning_comparison_path || null;
},
......@@ -371,7 +357,6 @@ export default {
<div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" />
<div class="mr-widget-info">
<section v-if="mr.allowCollaboration" class="mr-info-list mr-links">
<p>
......@@ -404,13 +389,6 @@ export default {
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
</div>
</div>
<merge-train-helper-text
v-if="shouldRenderMergeTrainHelperText"
:pipeline-id="mr.pipeline.id"
:pipeline-link="mr.pipeline.path"
:merge-train-length="mr.mergeTrainsCount"
:merge-train-when-pipeline-succeeds-docs-path="mr.mergeTrainWhenPipelineSucceedsDocsPath"
/>
<div v-if="shouldRenderMergeHelp" class="mr-widget-footer"><mr-widget-merge-help /></div>
</div>
<mr-widget-pipeline-container
......
---
title: Update Merge Train helper text
merge_request: 38619
author:
type: changed
......@@ -30,7 +30,7 @@ RSpec.describe 'User adds to merge train when pipeline succeeds', :js do
expect(page).to have_button('Start merge train when pipeline succeeds')
within('.js-merge-train-helper-text') do
expect(page).to have_content("This merge request will start a merge train when pipeline ##{pipeline.id} succeeds.")
expect(page).to have_content("This action will start a merge train when pipeline ##{pipeline.id} succeeds.")
expect(page).to have_link('More information',
href: MergeRequestPresenter.new(merge_request).merge_train_when_pipeline_succeeds_docs_path)
end
......
import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import { GlLink, GlSprintf } from '@gitlab/ui';
import { trimText } from 'helpers/text_helper';
import MergeTrainHelperText from 'ee/vue_merge_request_widget/components/merge_train_helper_text.vue';
describe('MergeTrainHelperText', () => {
let wrapper;
const factory = propsData => {
const defaultProps = {
pipelineId: 123,
pipelineLink: 'path/to/pipeline',
mergeTrainWhenPipelineSucceedsDocsPath: 'path/to/help',
mergeTrainLength: 2,
};
const findDocumentationLink = () => wrapper.find('[data-testid="documentation-link"]');
const findPipelineLink = () => wrapper.find('[data-testid="pipeline-link"]');
const createWrapper = propsData => {
wrapper = shallowMount(MergeTrainHelperText, {
propsData,
propsData: {
...defaultProps,
...propsData,
},
stubs: {
GlSprintf,
GlLink,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('should return the "start" version of the message if there is no existing merge train', () => {
factory({
pipelineId: 123,
pipelineLink: 'path/to/pipeline',
mergeTrainWhenPipelineSucceedsDocsPath: 'path/to/help',
mergeTrainLength: 0,
});
createWrapper({ mergeTrainLength: 0 });
expect(trimText(wrapper.text())).toBe(
'This merge request will start a merge train when pipeline #123 succeeds. More information',
'This action will start a merge train when pipeline #123 succeeds. More information',
);
});
it('should render the correct pipeline link in the helper text', () => {
factory({
pipelineId: 123,
pipelineLink: 'path/to/pipeline',
mergeTrainWhenPipelineSucceedsDocsPath: 'path/to/help',
mergeTrainLength: 2,
});
createWrapper();
const pipelineLink = wrapper.find('.js-pipeline-link').element;
const pipelineLink = findPipelineLink();
expect(pipelineLink).toExist();
expect(pipelineLink.textContent).toContain('#123');
expect(pipelineLink).toHaveAttr('href', 'path/to/pipeline');
});
it('should sanitize the pipeline link', () => {
factory({
pipelineId: 123,
pipelineLink: '"></a> <script>console.log("hacked!!")</script> <a href="',
mergeTrainWhenPipelineSucceedsDocsPath: 'path/to/help',
mergeTrainLength: 2,
});
const pipelineLink = wrapper.find('.js-pipeline-link').element;
expect(pipelineLink).toExist();
// The escaped characters are un-escaped when rendered by the DOM,
// so we expect the value of the "href" attr to be exactly the same
// as the input. If the link was not sanitized, the "href" attr
// would equal "".
expect(pipelineLink).toHaveAttr(
'href',
'"></a> <script>console.log("hacked!!")</script> <a href="',
);
expect(pipelineLink.exists()).toBe(true);
expect(pipelineLink.text()).toContain('#123');
expect(pipelineLink.attributes('href')).toBe(defaultProps.pipelineLink);
});
it('should render the correct documentation link in the helper text', () => {
factory({
pipelineId: 123,
pipelineLink: 'path/to/pipeline',
mergeTrainWhenPipelineSucceedsDocsPath: 'path/to/help',
mergeTrainLength: 2,
});
createWrapper();
const docLink = wrapper.find(GlLink);
expect(docLink.exists()).toBe(true);
expect(docLink.attributes().href).toBe('path/to/help');
expect(findDocumentationLink().exists()).toBe(true);
expect(findDocumentationLink().attributes('href')).toBe(
defaultProps.mergeTrainWhenPipelineSucceedsDocsPath,
);
});
});
import { shallowMount } from '@vue/test-utils';
import { MERGE_DISABLED_TEXT_UNAPPROVED } from 'ee/vue_merge_request_widget/mixins/ready_to_merge';
import MergeImmediatelyConfirmationDialog from 'ee/vue_merge_request_widget/components/merge_immediately_confirmation_dialog.vue';
import MergeTrainHelperText from 'ee/vue_merge_request_widget/components/merge_train_helper_text.vue';
import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
import {
MWPS_MERGE_STRATEGY,
......@@ -11,7 +12,7 @@ import {
MERGE_DISABLED_TEXT,
PIPELINE_MUST_SUCCEED_CONFLICT_TEXT,
} from '~/vue_merge_request_widget/mixins/ready_to_merge';
import { GlSprintf } from '@gitlab/ui';
import { GlLink, GlSprintf } from '@gitlab/ui';
describe('ReadyToMerge', () => {
let wrapper;
......@@ -22,9 +23,15 @@ describe('ReadyToMerge', () => {
poll: () => {},
};
const activePipeline = {
id: 1,
path: 'path/to/pipeline',
active: true,
};
const mr = {
isPipelineActive: false,
pipeline: null,
pipeline: { id: 1, path: 'path/to/pipeline' },
isPipelineFailed: false,
isPipelinePassing: false,
isMergeAllowed: true,
......@@ -46,6 +53,8 @@ describe('ReadyToMerge', () => {
preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY,
availableAutoMergeStrategies: [MWPS_MERGE_STRATEGY],
mergeImmediatelyDocsPath: 'path/to/merge/immediately/docs',
mergeTrainWhenPipelineSucceedsDocsPath: '/merge-train/docs',
mergeTrainsCount: 0,
};
const factory = (mrUpdates = {}) => {
......@@ -56,6 +65,9 @@ describe('ReadyToMerge', () => {
},
stubs: {
MergeImmediatelyConfirmationDialog,
MergeTrainHelperText,
GlSprintf,
GlLink,
},
});
......@@ -63,12 +75,22 @@ describe('ReadyToMerge', () => {
};
const findResolveItemsMessage = () => wrapper.find(GlSprintf);
const findPipelineConflictMessage = () =>
wrapper.find('[data-testid="pipeline-succeed-conflict"]');
const findMergeButton = () => wrapper.find('.qa-merge-button');
const findMergeButtonDropdown = () => wrapper.find('.js-merge-moment');
const findMergeImmediatelyButton = () => wrapper.find('.js-merge-immediately-button');
const findMergeTrainHelperText = () => wrapper.find(MergeTrainHelperText);
const findMergeTrainPipelineLink = () =>
findMergeTrainHelperText().find('[data-testid="pipeline-link"]');
const findMergeTrainDocumentationLink = () =>
findMergeTrainHelperText().find('[data-testid="documentation-link"]');
afterEach(() => {
if (wrapper?.destroy) {
wrapper.destroy();
wrapper = null;
}
});
describe('computed', () => {
......@@ -178,6 +200,87 @@ describe('ReadyToMerge', () => {
});
});
describe('shouldRenderMergeTrainHelperText', () => {
it('should render the helper text if MTWPS is available and the user has not yet pressed the MTWPS button', () => {
factory({
onlyAllowMergeIfPipelineSucceeds: true,
preferredAutoMergeStrategy: MTWPS_MERGE_STRATEGY,
autoMergeEnabled: false,
});
expect(findMergeTrainHelperText().exists()).toBe(true);
});
});
describe('merge train helper text', () => {
it('does not render the merge train helper text if the MTWPS strategy is not available', () => {
factory({
availableAutoMergeStrategies: [MT_MERGE_STRATEGY],
pipeline: activePipeline,
});
expect(findMergeTrainHelperText().exists()).toBe(false);
});
it('renders the correct merge train helper text when there is an existing merge train', () => {
factory({
onlyAllowMergeIfPipelineSucceeds: true,
preferredAutoMergeStrategy: MTWPS_MERGE_STRATEGY,
autoMergeEnabled: false,
mergeTrainsCount: 2,
pipeline: activePipeline,
});
expect(findMergeTrainHelperText().text()).toContain(
`This action will add the merge request to the merge train when pipeline #${activePipeline.id} succeeds.`,
);
});
it('renders the correct merge train helper text when there is no existing merge train', () => {
factory({
onlyAllowMergeIfPipelineSucceeds: true,
preferredAutoMergeStrategy: MTWPS_MERGE_STRATEGY,
autoMergeEnabled: false,
mergeTrainsCount: 0,
pipeline: activePipeline,
});
expect(findMergeTrainHelperText().text()).toContain(
`This action will start a merge train when pipeline #${activePipeline.id} succeeds.`,
);
});
it('renders the correct pipeline link inside the message', () => {
factory({
onlyAllowMergeIfPipelineSucceeds: true,
preferredAutoMergeStrategy: MTWPS_MERGE_STRATEGY,
autoMergeEnabled: false,
mergeTrainsCount: 0,
pipeline: activePipeline,
});
const pipelineLink = findMergeTrainPipelineLink();
expect(pipelineLink.text()).toContain(activePipeline.id);
expect(pipelineLink.attributes('href')).toBe(activePipeline.path);
});
it('renders the documentation link inside the message', () => {
factory({
onlyAllowMergeIfPipelineSucceeds: true,
preferredAutoMergeStrategy: MTWPS_MERGE_STRATEGY,
autoMergeEnabled: false,
mergeTrainsCount: 0,
pipeline: activePipeline,
});
const pipelineLink = findMergeTrainDocumentationLink();
expect(pipelineLink.text()).toContain('More information');
expect(pipelineLink.attributes('href')).toBe(mr.mergeTrainWhenPipelineSucceedsDocsPath);
});
});
describe('shouldShowMergeImmediatelyDropdown', () => {
it('should return false if no pipeline is active', () => {
factory({
......@@ -275,7 +378,7 @@ describe('ReadyToMerge', () => {
});
it('should show cannot merge text', () => {
expect(findResolveItemsMessage().attributes('message')).toBe(MERGE_DISABLED_TEXT);
expect(findResolveItemsMessage().text()).toBe(MERGE_DISABLED_TEXT);
});
it('should show disabled merge button', () => {
......@@ -298,7 +401,7 @@ describe('ReadyToMerge', () => {
});
it('should show approvals needed text', () => {
expect(findResolveItemsMessage().attributes('message')).toBe(MERGE_DISABLED_TEXT_UNAPPROVED);
expect(findResolveItemsMessage().text()).toBe(MERGE_DISABLED_TEXT_UNAPPROVED);
});
});
......@@ -313,9 +416,7 @@ describe('ReadyToMerge', () => {
});
it('should show a custom message that explains the conflict', () => {
expect(findResolveItemsMessage().attributes('message')).toBe(
PIPELINE_MUST_SUCCEED_CONFLICT_TEXT,
);
expect(findPipelineConflictMessage().text()).toBe(PIPELINE_MUST_SUCCEED_CONFLICT_TEXT);
});
});
});
......@@ -16,7 +16,6 @@ import mockData, {
import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
import { MTWPS_MERGE_STRATEGY, MT_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
import {
sastDiffSuccessMock,
dastDiffSuccessMock,
......@@ -942,20 +941,6 @@ describe('ee merge request widget options', () => {
expect(vm.shouldRenderApprovals).toBeTruthy();
});
});
describe('shouldRenderMergeTrainHelperText', () => {
it('should return true if MTWPS is available and the user has not yet pressed the MTWPS button', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MTWPS_MERGE_STRATEGY],
auto_merge_enabled: false,
},
});
expect(vm.shouldRenderMergeTrainHelperText).toBe(true);
});
});
});
describe('rendering source branch removal status', () => {
......@@ -1054,115 +1039,6 @@ describe('ee merge request widget options', () => {
});
});
describe('merge train helper text', () => {
const getHelperTextElement = () => vm.$el.querySelector('.js-merge-train-helper-text');
it('does not render the merge train helpe text if the MTWPS strategy is not available', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MT_MERGE_STRATEGY],
pipeline: {
...mockData.pipeline,
active: true,
},
},
});
const helperText = getHelperTextElement();
expect(helperText).not.toExist();
});
it('renders the correct merge train helper text when there is an existing merge train', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MTWPS_MERGE_STRATEGY],
merge_trains_count: 2,
merge_train_when_pipeline_succeeds_docs_path: 'path/to/help',
pipeline: {
...mockData.pipeline,
id: 123,
active: true,
},
},
});
const helperText = getHelperTextElement();
expect(helperText).toExist();
expect(helperText.textContent).toContain(
'This merge request will be added to the merge train when pipeline #123 succeeds.',
);
});
it('renders the correct merge train helper text when there is no existing merge train', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MTWPS_MERGE_STRATEGY],
merge_trains_count: 0,
merge_train_when_pipeline_succeeds_docs_path: 'path/to/help',
pipeline: {
...mockData.pipeline,
id: 123,
active: true,
},
},
});
const helperText = getHelperTextElement();
expect(helperText).toExist();
expect(helperText.textContent).toContain(
'This merge request will start a merge train when pipeline #123 succeeds.',
);
});
it('renders the correct pipeline link inside the message', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MTWPS_MERGE_STRATEGY],
merge_train_when_pipeline_succeeds_docs_path: 'path/to/help',
pipeline: {
...mockData.pipeline,
id: 123,
path: 'path/to/pipeline',
active: true,
},
},
});
const pipelineLink = getHelperTextElement().querySelector('.js-pipeline-link');
expect(pipelineLink).toExist();
expect(pipelineLink.textContent).toContain('#123');
expect(pipelineLink).toHaveAttr('href', 'path/to/pipeline');
});
it('renders the documentation link inside the message', () => {
vm = mountComponent(Component, {
mrData: {
...mockData,
available_auto_merge_strategies: [MTWPS_MERGE_STRATEGY],
merge_train_when_pipeline_succeeds_docs_path: 'path/to/help',
pipeline: {
...mockData.pipeline,
active: true,
},
},
});
const pipelineLink = getHelperTextElement().querySelector('.js-documentation-link');
expect(pipelineLink).toExist();
expect(pipelineLink.textContent).toContain('More information');
expect(pipelineLink).toHaveAttr('href', 'path/to/help');
});
});
describe('data', () => {
it('passes approval api paths to service', () => {
const paths = {
......
......@@ -29333,19 +29333,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
msgid "mrWidget|This merge request failed to be merged automatically"
msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
msgid "mrWidget|This merge request is in the process of being merged"
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
......
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