Commit 2c73fd2e authored by Miguel Rincon's avatar Miguel Rincon

Merge branch...

Merge branch '218084-merge-widget-gives-ambiguous-ui-instructions-when-merge-trains-are-enabled' into 'master'

MR widget instructions are unclear when merge trains are enabled

Closes #218084

See merge request gitlab-org/gitlab!38619
parents 9289e85a ed092037
......@@ -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,42 +27,35 @@ export default {
},
},
computed: {
message() {
const text =
this.mergeTrainLength === 0
? s__(
'mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} 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,
);
helperMessage() {
return this.mergeTrainLength === 0
? s__(
'mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds.',
)
: s__(
'mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds.',
);
},
},
};
</script>
<template>
<section class="js-merge-train-helper-text mr-widget-help border-top">
<span v-html="message"></span>
<gl-link
:href="mergeTrainWhenPipelineSucceedsDocsPath"
target="_blank"
rel="noopener noreferrer"
class="js-documentation-link"
>
{{ s__('mrWidget|More information') }}
</gl-link>
<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"
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,
});
const docLink = wrapper.find(GlLink);
createWrapper();
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(() => {
wrapper.destroy();
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