Commit 4dd5bd4c authored by Phil Hughes's avatar Phil Hughes

Merge branch '33095-mr-widget-ui-ee' into 'master'

33095 mr widget ui ee

See merge request !2389
parents 9567a1ee a5331438
...@@ -8,8 +8,8 @@ export default { ...@@ -8,8 +8,8 @@ export default {
template: ` template: `
<a <a
:href="author.webUrl || author.web_url" :href="author.webUrl || author.web_url"
class="author-link" class="author-link inline"
:class="{ 'has-tooltip': showAuthorTooltip }" :v-tooltip="showAuthorTooltip"
:title="author.name"> :title="author.name">
<img <img
:src="author.avatarUrl || author.avatar_url" :src="author.avatarUrl || author.avatar_url"
......
/* global Flash */ /* global Flash */
import '~/lib/utils/datetime_utility'; import '~/lib/utils/datetime_utility';
import { statusIconEntityMap } from '../../vue_shared/ci_status_icons';
import MemoryUsage from './mr_widget_memory_usage'; import MemoryUsage from './mr_widget_memory_usage';
import StatusIcon from './mr_widget_status_icon';
import MRWidgetService from '../services/mr_widget_service'; import MRWidgetService from '../services/mr_widget_service';
export default { export default {
...@@ -13,11 +13,7 @@ export default { ...@@ -13,11 +13,7 @@ export default {
}, },
components: { components: {
'mr-widget-memory-usage': MemoryUsage, 'mr-widget-memory-usage': MemoryUsage,
}, 'status-icon': StatusIcon,
computed: {
svg() {
return statusIconEntityMap.icon_status_success;
},
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
...@@ -51,16 +47,15 @@ export default { ...@@ -51,16 +47,15 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-heading"> <div class="mr-widget-heading deploy-heading">
<div v-for="deployment in mr.deployments"> <div v-for="deployment in mr.deployments">
<div class="ci-widget"> <div class="ci-widget media">
<div class="ci-status-icon ci-status-icon-success"> <div class="ci-status-icon ci-status-icon-success">
<span class="js-icon-link icon-link"> <span class="js-icon-link icon-link">
<span class="ci-status-icon" <status-icon status="success" />
v-html="svg"
aria-hidden="true"></span>
</span> </span>
</div> </div>
<div class="media-body space-children">
<span> <span>
<span <span
v-if="hasDeploymentMeta(deployment)"> v-if="hasDeploymentMeta(deployment)">
...@@ -71,7 +66,7 @@ export default { ...@@ -71,7 +66,7 @@ export default {
:href="deployment.url" :href="deployment.url"
target="_blank" target="_blank"
rel="noopener noreferrer nofollow" rel="noopener noreferrer nofollow"
class="js-deploy-meta"> class="js-deploy-meta inline">
{{deployment.name}} {{deployment.name}}
</a> </a>
<span <span
...@@ -83,7 +78,7 @@ export default { ...@@ -83,7 +78,7 @@ export default {
:href="deployment.external_url" :href="deployment.external_url"
target="_blank" target="_blank"
rel="noopener noreferrer nofollow" rel="noopener noreferrer nofollow"
class="js-deploy-url"> class="js-deploy-url inline">
<i <i
class="fa fa-external-link" class="fa fa-external-link"
aria-hidden="true" /> aria-hidden="true" />
...@@ -97,6 +92,7 @@ export default { ...@@ -97,6 +92,7 @@ export default {
data-placement="top"> data-placement="top">
{{formatDate(deployment.deployed_at)}} {{formatDate(deployment.deployed_at)}}
</span> </span>
</span>
<button <button
type="button" type="button"
v-if="deployment.stop_url" v-if="deployment.stop_url"
...@@ -104,8 +100,6 @@ export default { ...@@ -104,8 +100,6 @@ export default {
class="btn btn-default btn-xs"> class="btn btn-default btn-xs">
Stop environment Stop environment
</button> </button>
</span>
</div>
<mr-widget-memory-usage <mr-widget-memory-usage
v-if="deployment.metrics_url" v-if="deployment.metrics_url"
:metrics-url="deployment.metrics_url" :metrics-url="deployment.metrics_url"
...@@ -113,5 +107,7 @@ export default { ...@@ -113,5 +107,7 @@ export default {
/> />
</div> </div>
</div> </div>
</div>
</div>
`, `,
}; };
...@@ -35,12 +35,12 @@ export default { ...@@ -35,12 +35,12 @@ export default {
<a <a
href="#modal_merge_info" href="#modal_merge_info"
data-toggle="modal" data-toggle="modal"
class="btn inline btn-grouped btn-sm"> class="btn inline btn-grouped">
Check out branch Check out branch
</a> </a>
<span class="dropdown inline prepend-left-5"> <span class="dropdown inline prepend-left-10">
<a <a
class="btn btn-sm dropdown-toggle" class="btn dropdown-toggle"
data-toggle="dropdown" data-toggle="dropdown"
aria-label="Download as" aria-label="Download as"
role="button"> role="button">
......
...@@ -120,13 +120,12 @@ export default { ...@@ -120,13 +120,12 @@ export default {
}, },
template: ` template: `
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage"> <div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<div class="legend"></div>
<p <p
v-if="shouldShowLoading" v-if="shouldShowLoading"
class="usage-info js-usage-info usage-info-loading"> class="usage-info js-usage-info usage-info-loading">
<i <i
class="fa fa-spinner fa-spin usage-info-load-spinner" class="fa fa-spinner fa-spin usage-info-load-spinner"
aria-hidden="true" />Loading deployment statistics. aria-hidden="true" />Loading deployment statistics
</p> </p>
<p <p
v-if="shouldShowMemoryGraph" v-if="shouldShowMemoryGraph"
...@@ -136,12 +135,12 @@ export default { ...@@ -136,12 +135,12 @@ export default {
<p <p
v-if="shouldShowLoadFailure" v-if="shouldShowLoadFailure"
class="usage-info js-usage-info usage-info-failed"> class="usage-info js-usage-info usage-info-failed">
Failed to load deployment statistics. Failed to load deployment statistics
</p> </p>
<p <p
v-if="shouldShowMetricsUnavailable" v-if="shouldShowMetricsUnavailable"
class="usage-info js-usage-info usage-info-unavailable"> class="usage-info js-usage-info usage-info-unavailable">
Deployment statistics are not available currently. Deployment statistics are not available currently
</p> </p>
<mr-memory-graph <mr-memory-graph
v-if="shouldShowMemoryGraph" v-if="shouldShowMemoryGraph"
......
...@@ -16,7 +16,7 @@ export default { ...@@ -16,7 +16,7 @@ export default {
<a <a
data-toggle="modal" data-toggle="modal"
href="#modal_merge_info"> href="#modal_merge_info">
command line. command line
</a> </a>
</section> </section>
`, `,
......
...@@ -44,38 +44,34 @@ export default { ...@@ -44,38 +44,34 @@ export default {
}, },
template: ` template: `
<div class="mr-widget-heading"> <div class="mr-widget-heading">
<div class="ci-widget"> <div class="ci-widget media">
<template v-if="hasCIError"> <template v-if="hasCIError">
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error"> <div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-10">
<span class="js-icon-link icon-link">
<span <span
v-html="svg" v-html="svg"
aria-hidden="true"></span> aria-hidden="true"></span>
</span>
</div> </div>
<span>Could not connect to the CI server. Please check your settings and try again.</span> <div class="media-body">
Could not connect to the CI server. Please check your settings and try again
</div>
</template> </template>
<template v-else> <template v-else>
<div> <div class="ci-status-icon append-right-10">
<a <a
class="icon-link" class="icon-link"
:href="this.status.details_path"> :href="this.status.details_path">
<ci-icon :status="status" /> <ci-icon :status="status" />
</a> </a>
</div> </div>
<div class="media-body">
<span> <span>
Pipeline Pipeline
<a <a
:href="mr.pipeline.path" :href="mr.pipeline.path"
class="pipeline-id">#{{mr.pipeline.id}}</a> class="pipeline-id">#{{mr.pipeline.id}}</a>
{{mr.pipeline.details.status.label}}
</span> </span>
<span <span class="mr-widget-pipeline-graph">
v-if="mr.pipeline.details.stages.length > 0"> <span class="stage-cell">
with {{stageText}}
</span>
<div class="mr-widget-pipeline-graph">
<div class="stage-cell">
<linked-pipelines-mini-list <linked-pipelines-mini-list
v-if="triggeredBy.length" v-if="triggeredBy.length"
:triggered-by="triggeredBy" :triggered-by="triggeredBy"
...@@ -95,10 +91,10 @@ export default { ...@@ -95,10 +91,10 @@ export default {
v-if="triggered.length" v-if="triggered.length"
:triggered="triggered" :triggered="triggered"
/> />
</div> </span>
</div> </span>
<span> <span>
for {{mr.pipeline.details.status.label}} for
<a <a
:href="mr.pipeline.commit.commit_path" :href="mr.pipeline.commit.commit_path"
class="commit-sha js-commit-link"> class="commit-sha js-commit-link">
...@@ -107,8 +103,9 @@ export default { ...@@ -107,8 +103,9 @@ export default {
<span <span
v-if="mr.pipeline.coverage" v-if="mr.pipeline.coverage"
class="js-mr-coverage"> class="js-mr-coverage">
Coverage {{mr.pipeline.coverage}}%. Coverage {{mr.pipeline.coverage}}%
</span> </span>
</div>
</template> </template>
</div> </div>
</div> </div>
......
...@@ -2,6 +2,7 @@ export default { ...@@ -2,6 +2,7 @@ export default {
name: 'MRWidgetRelatedLinks', name: 'MRWidgetRelatedLinks',
props: { props: {
relatedLinks: { type: Object, required: true }, relatedLinks: { type: Object, required: true },
state: { type: String },
}, },
computed: { computed: {
hasLinks() { hasLinks() {
...@@ -10,29 +11,25 @@ export default { ...@@ -10,29 +11,25 @@ export default {
}, },
}, },
methods: { methods: {
hasMultipleIssues(text) { closesText(state) {
return !text ? false : text.match(/<\/a> and <a/); if (state === 'merged') {
}, return 'Closed';
issueLabel(field) { }
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'issues' : 'issue'; if (state === 'closed') {
}, return 'Did not close';
verbLabel(field) { }
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'are' : 'is'; return 'Closes';
}, },
}, },
template: ` template: `
<section <section
v-if="hasLinks" v-if="hasLinks"
class="mr-info-list mr-links"> class="mr-info-list mr-links">
<div class="legend"></div>
<p v-if="relatedLinks.closing"> <p v-if="relatedLinks.closing">
Closes {{issueLabel('closing')}} {{closesText(state)}} <span v-html="relatedLinks.closing"></span>
<span v-html="relatedLinks.closing"></span>.
</p> </p>
<p v-if="relatedLinks.mentioned"> <p v-if="relatedLinks.mentioned">
<span class="capitalize">{{issueLabel('mentioned')}}</span> Mentions <span v-html="relatedLinks.mentioned"></span>
<span v-html="relatedLinks.mentioned"></span>
{{verbLabel('mentioned')}} mentioned but will not be closed.
</p> </p>
<p v-if="relatedLinks.assignToMe"> <p v-if="relatedLinks.assignToMe">
<span v-html="relatedLinks.assignToMe"></span> <span v-html="relatedLinks.assignToMe"></span>
......
import ciIcon from '../../vue_shared/components/ci_icon.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
status: { type: String, required: true },
showDisabledButton: { type: Boolean, required: false },
},
components: {
ciIcon,
loadingIcon,
},
computed: {
statusObj() {
return {
group: this.status,
icon: `icon_status_${this.status}`,
};
},
},
template: `
<div class="space-children flex-container-block append-right-10">
<div v-if="status === 'loading'" class="mr-widget-icon">
<loading-icon />
</div>
<ci-icon v-else :status="statusObj" />
<button
v-if="showDisabledButton"
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
</div>
`,
};
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetArchived', name: 'MRWidgetArchived',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<div class="space-children">
<status-icon status="failed" />
<button <button
type="button" type="button"
class="btn btn-success btn-small" class="btn btn-success btn-small"
disabled="true"> disabled="true">
Merge Merge
</button> </button>
</div>
<div class="media-body">
<span class="bold"> <span class="bold">
This project is archived, write access has been disabled. This project is archived, write access has been disabled
</span> </span>
</div> </div>
</div>
`, `,
}; };
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetAutoMergeFailed', name: 'MRWidgetAutoMergeFailed',
...@@ -10,6 +11,9 @@ export default { ...@@ -10,6 +11,9 @@ export default {
isRefreshing: false, isRefreshing: false,
}; };
}, },
components: {
statusIcon,
},
methods: { methods: {
refreshWidget() { refreshWidget() {
this.isRefreshing = true; this.isRefreshing = true;
...@@ -19,18 +23,16 @@ export default { ...@@ -19,18 +23,16 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" />
class="btn btn-success btn-small" <div class="media-body space-children">
disabled="true" <span class="bold">
type="button"> <template v-if="mr.mergeError">{{mr.mergeError}}.</template>
Merge This merge request failed to be merged automatically
</button> </span>
<span class="bold danger">
This merge request failed to be merged automatically.
<button <button
@click="refreshWidget" @click="refreshWidget"
:class="{ disabled: isRefreshing }" :disabled="isRefreshing"
type="button" type="button"
class="btn btn-xs btn-default"> class="btn btn-xs btn-default">
<i <i
...@@ -39,9 +41,6 @@ export default { ...@@ -39,9 +41,6 @@ export default {
aria-hidden="true" /> aria-hidden="true" />
Refresh Refresh
</button> </button>
</span>
<div class="merge-error-text danger bold">
{{mr.mergeError}}
</div> </div>
</div> </div>
`, `,
......
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetChecking', name: 'MRWidgetChecking',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="loading" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
Checking ability to merge automatically. Checking ability to merge automatically
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</span> </span>
</div> </div>
</div>
`, `,
}; };
import mrWidgetAuthorTime from '../../components/mr_widget_author_time'; import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetClosed', name: 'MRWidgetClosed',
...@@ -7,24 +8,28 @@ export default { ...@@ -7,24 +8,28 @@ export default {
}, },
components: { components: {
'mr-widget-author-and-time': mrWidgetAuthorTime, 'mr-widget-author-and-time': mrWidgetAuthorTime,
statusIcon,
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<status-icon status="failed" />
<div class="media-body">
<mr-widget-author-and-time <mr-widget-author-and-time
actionText="Closed by" actionText="Closed by"
:author="mr.closedBy" :author="mr.closedBy"
:dateTitle="mr.updatedAt" :dateTitle="mr.updatedAt"
:dateReadable="mr.closedAt" :dateReadable="mr.closedAt"
/> />
<section> <section class="mr-info-list">
<p> <p>
The changes were not merged into The changes were not merged into
<a <a
:href="mr.targetBranchPath" :href="mr.targetBranchPath"
class="label-branch"> class="label-branch">
{{mr.targetBranch}}</a>. {{mr.targetBranch}}</a>
</p> </p>
</section> </section>
</div> </div>
</div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetConflicts', name: 'MRWidgetConflicts',
props: { props: {
mr: { type: Object, required: true }, mr: { type: Object, required: true },
}, },
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
There are merge conflicts. There are merge conflicts<span v-if="!mr.canMerge">.</span>
<span v-if="!mr.canMerge"> <span v-if="!mr.canMerge">
Resolve these conflicts or ask someone with write access to this repository to merge it locally. Resolve these conflicts or ask someone with write access to this repository to merge it locally.
</span> </span>
</span> </span>
<div
v-if="mr.canMerge"
class="btn-group">
<a <a
v-if="mr.conflictResolutionPath" v-if="mr.canMerge && mr.conflictResolutionPath"
:href="mr.conflictResolutionPath" :href="mr.conflictResolutionPath"
class="btn btn-default btn-xs js-resolve-conflicts-button"> class="btn btn-default btn-xs js-resolve-conflicts-button">
Resolve conflicts Resolve conflicts
......
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
...@@ -38,39 +39,40 @@ export default { ...@@ -38,39 +39,40 @@ export default {
} }
}, },
}, },
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <template v-if="isRefreshing">
class="btn btn-success btn-small" <status-icon status="loading" />
disabled="true" <span class="media-body bold js-refresh-label">
type="button"> Refreshing now
Merge </span>
</button> </template>
<span <template v-else>
v-if="!isRefreshing" <status-icon status="failed" showDisabledButton />
class="bold danger"> <div class="media-body space-children">
<span class="bold">
<span <span
class="has-error-message" class="has-error-message"
v-if="mr.mergeError"> v-if="mr.mergeError">
{{mr.mergeError}} {{mr.mergeError}}.
</span> </span>
<span v-else>Merge failed.</span> <span v-else>Merge failed.</span>
<span <span
:class="{ 'has-custom-error': mr.mergeError }"> :class="{ 'has-custom-error': mr.mergeError }">
Refreshing in {{timerText}} to show the updated status... Refreshing in {{timerText}} to show the updated status...
</span> </span>
</span>
<button <button
@click="refresh" @click="refresh"
class="btn btn-default btn-xs js-refresh-button" class="btn btn-default btn-xs js-refresh-button"
type="button"> type="button">
Refresh now Refresh now
</button> </button>
</span> </div>
<span </template>
v-if="isRefreshing"
class="bold js-refresh-label">
Refreshing now...
</span>
</div> </div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetLocked', name: 'MRWidgetLocked',
props: { props: {
mr: { type: Object, required: true }, mr: { type: Object, required: true },
}, },
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body mr-state-locked"> <div class="mr-widget-body mr-state-locked media">
<span class="state-label">Locked</span> <status-icon status="loading" />
This merge request is in the process of being merged, during which time it is locked and cannot be closed. <div class="media-body">
<i <h4>
class="fa fa-spinner fa-spin" This merge request is in the process of being merged, during which time it is locked and cannot be closed
aria-hidden="true" /> </h4>
<section class="mr-info-list mr-links"> <section class="mr-info-list">
<div class="legend"></div>
<p> <p>
The changes will be merged into The changes will be merged into
<span class="label-branch"> <span class="label-branch">
<a :href="mr.targetBranchPath">{{mr.targetBranch}}</a> <a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
</span>. </span>
</p> </p>
</section> </section>
</div> </div>
</div>
`, `,
}; };
/* global Flash */ /* global Flash */
import statusIcon from '../mr_widget_status_icon';
import MRWidgetAuthor from '../../components/mr_widget_author'; import MRWidgetAuthor from '../../components/mr_widget_author';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
...@@ -11,6 +11,7 @@ export default { ...@@ -11,6 +11,7 @@ export default {
}, },
components: { components: {
'mr-widget-author': MRWidgetAuthor, 'mr-widget-author': MRWidgetAuthor,
statusIcon,
}, },
data() { data() {
return { return {
...@@ -61,11 +62,13 @@ export default { ...@@ -61,11 +62,13 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<status-icon status="success" />
<div class="media-body">
<h4> <h4>
Set by Set by
<mr-widget-author :author="mr.setToMWPSBy" /> <mr-widget-author :author="mr.setToMWPSBy" />
to be merged automatically when the pipeline succeeds. to be merged automatically when the pipeline succeeds
<a <a
v-if="mr.canCancelAutomaticMerge" v-if="mr.canCancelAutomaticMerge"
@click.prevent="cancelAutomaticMerge" @click.prevent="cancelAutomaticMerge"
...@@ -81,21 +84,18 @@ export default { ...@@ -81,21 +84,18 @@ export default {
</a> </a>
</h4> </h4>
<section class="mr-info-list"> <section class="mr-info-list">
<div class="legend"></div>
<p>The changes will be merged into <p>The changes will be merged into
<a <a
:href="mr.targetBranchPath" :href="mr.targetBranchPath"
class="label-branch"> class="label-branch">
{{mr.targetBranch}} {{mr.targetBranch}}
</a>. </a>
</p> </p>
<p v-if="mr.shouldRemoveSourceBranch"> <p v-if="mr.shouldRemoveSourceBranch">
The source branch will be removed. The source branch will be removed
</p> </p>
<p <p v-else>
v-else The source branch will not be removed
class="with-button">
The source branch will not be removed.
<a <a
v-if="canRemoveSourceBranch" v-if="canRemoveSourceBranch"
:disabled="isRemovingSourceBranch" :disabled="isRemovingSourceBranch"
...@@ -112,5 +112,6 @@ export default { ...@@ -112,5 +112,6 @@ export default {
</p> </p>
</section> </section>
</div> </div>
</div>
`, `,
}; };
/* global Flash */ /* global Flash */
import mrWidgetAuthorTime from '../../components/mr_widget_author_time'; import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
...@@ -11,6 +12,7 @@ export default { ...@@ -11,6 +12,7 @@ export default {
}, },
components: { components: {
'mr-widget-author-and-time': mrWidgetAuthorTime, 'mr-widget-author-and-time': mrWidgetAuthorTime,
statusIcon,
}, },
data() { data() {
return { return {
...@@ -55,44 +57,18 @@ export default { ...@@ -55,44 +57,18 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<status-icon status="success" />
<div class="media-body">
<div class="space-children">
<mr-widget-author-and-time <mr-widget-author-and-time
actionText="Merged by" actionText="Merged by"
:author="mr.mergedBy" :author="mr.mergedBy"
:dateTitle="mr.updatedAt" :dateTitle="mr.updatedAt"
:dateReadable="mr.mergedAt" /> :dateReadable="mr.mergedAt" />
<section class="mr-info-list">
<div class="legend"></div>
<p>
The changes were merged into
<span class="label-branch">
<a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
</span>
</p>
<p v-if="mr.sourceBranchRemoved">The source branch has been removed.</p>
<p v-if="shouldShowRemoveSourceBranch">
You can remove source branch now.
<button
@click="removeSourceBranch"
:class="{ disabled: isMakingRequest }"
type="button"
class="btn btn-xs btn-default js-remove-branch-button">
Remove Source Branch
</button>
</p>
<p v-if="shouldShowSourceBranchRemoving">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
The source branch is being removed.
</p>
</section>
<div
v-if="shouldShowMergedButtons"
class="merged-buttons clearfix">
<a <a
v-if="mr.canRevertInCurrentMR" v-if="mr.canRevertInCurrentMR"
class="btn btn-close btn-sm has-tooltip" class="btn btn-close btn-xs has-tooltip"
href="#modal-revert-commit" href="#modal-revert-commit"
data-toggle="modal" data-toggle="modal"
data-container="body" data-container="body"
...@@ -101,7 +77,7 @@ export default { ...@@ -101,7 +77,7 @@ export default {
</a> </a>
<a <a
v-else-if="mr.revertInForkPath" v-else-if="mr.revertInForkPath"
class="btn btn-close btn-sm has-tooltip" class="btn btn-close btn-xs has-tooltip"
data-method="post" data-method="post"
:href="mr.revertInForkPath" :href="mr.revertInForkPath"
title="Revert this merge request in a new merge request"> title="Revert this merge request in a new merge request">
...@@ -109,7 +85,7 @@ export default { ...@@ -109,7 +85,7 @@ export default {
</a> </a>
<a <a
v-if="mr.canCherryPickInCurrentMR" v-if="mr.canCherryPickInCurrentMR"
class="btn btn-default btn-sm has-tooltip" class="btn btn-default btn-xs has-tooltip"
href="#modal-cherry-pick-commit" href="#modal-cherry-pick-commit"
data-toggle="modal" data-toggle="modal"
data-container="body" data-container="body"
...@@ -118,13 +94,37 @@ export default { ...@@ -118,13 +94,37 @@ export default {
</a> </a>
<a <a
v-else-if="mr.cherryPickInForkPath" v-else-if="mr.cherryPickInForkPath"
class="btn btn-default btn-sm has-tooltip" class="btn btn-default btn-xs has-tooltip"
data-method="post" data-method="post"
:href="mr.cherryPickInForkPath" :href="mr.cherryPickInForkPath"
title="Cherry-pick this merge request in a new merge request"> title="Cherry-pick this merge request in a new merge request">
Cherry-pick Cherry-pick
</a> </a>
</div> </div>
<section class="mr-info-list">
<p>
The changes were merged into
<span class="label-branch">
<a :href="mr.targetBranchPath">{{mr.targetBranch}}</a>
</span>
</p>
<p v-if="mr.sourceBranchRemoved">The source branch has been removed</p>
<p v-if="shouldShowRemoveSourceBranch" class="space-children">
<span>You can remove source branch now</span>
<button
@click="removeSourceBranch"
:class="{ disabled: isMakingRequest }"
type="button"
class="btn btn-xs btn-default js-remove-branch-button">
Remove Source Branch
</button>
</p>
<p v-if="shouldShowSourceBranchRemoving">
<status-icon status="loading" />
<span>The source branch is being removed</span>
</p>
</section>
</div>
</div> </div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
import mrWidgetMergeHelp from '../../components/mr_widget_merge_help'; import mrWidgetMergeHelp from '../../components/mr_widget_merge_help';
export default { export default {
...@@ -7,28 +8,30 @@ export default { ...@@ -7,28 +8,30 @@ export default {
}, },
components: { components: {
'mr-widget-merge-help': mrWidgetMergeHelp, 'mr-widget-merge-help': mrWidgetMergeHelp,
statusIcon,
}, },
computed: { computed: {
missingBranchName() { missingBranchName() {
return this.mr.sourceBranchRemoved ? 'source' : 'target'; return this.mr.sourceBranchRemoved ? 'source' : 'target';
}, },
message() {
return `If the ${this.missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line`;
},
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold js-branch-text"> <span class="bold js-branch-text">
<span class="capitalize"> <span class="capitalize">
{{missingBranchName}} {{missingBranchName}}
</span> branch does not exist. </span> branch does not exist.
Please restore the {{missingBranchName}} branch or use a different {{missingBranchName}} branch. Please restore it or use a different {{missingBranchName}} branch
<i
class="fa fa-question-circle has-tooltip"
:title="message" />
</span> </span>
<mr-widget-merge-help </div>
:missing-branch="missingBranchName" />
</div> </div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetNotAllowed', name: 'MRWidgetNotAllowed',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="success" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
Ready to be merged automatically. Ready to be merged automatically.
Ask someone with write access to this repository to merge this request. Ask someone with write access to this repository to merge this request
</span> </span>
</div> </div>
</div>
`, `,
}; };
...@@ -12,7 +12,7 @@ export default { ...@@ -12,7 +12,7 @@ export default {
return { emptyStateSVG }; return { emptyStateSVG };
}, },
template: ` template: `
<div class="mr-widget-body empty-state"> <div class="mr-widget-body mr-widget-empty-state">
<div class="row"> <div class="row">
<div class="artwork col-sm-5 col-sm-push-7 col-xs-12 text-center"> <div class="artwork col-sm-5 col-sm-push-7 col-xs-12 text-center">
<span v-html="emptyStateSVG"></span> <span v-html="emptyStateSVG"></span>
...@@ -29,6 +29,7 @@ export default { ...@@ -29,6 +29,7 @@ export default {
Currently there are no changes in this merge request's source branch. Currently there are no changes in this merge request's source branch.
Please push new commits or use a different branch. Please push new commits or use a different branch.
</p> </p>
<div>
<a <a
v-if="mr.newBlobPath" v-if="mr.newBlobPath"
:href="mr.newBlobPath" :href="mr.newBlobPath"
...@@ -38,5 +39,6 @@ export default { ...@@ -38,5 +39,6 @@ export default {
</div> </div>
</div> </div>
</div> </div>
</div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetPipelineBlocked', name: 'MRWidgetPipelineBlocked',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
Pipeline blocked. The pipeline for this merge request requires a manual action to proceed. Pipeline blocked. The pipeline for this merge request requires a manual action to proceed
</span> </span>
</div> </div>
</div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetPipelineBlocked', name: 'MRWidgetPipelineBlocked',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
class="btn btn-success btn-small" <div class="media-body space-children">
disabled="true"
type="button">
Merge
</button>
<span class="bold"> <span class="bold">
The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure. The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
</span> </span>
</div> </div>
</div>
`, `,
}; };
/* global Flash */ /* global Flash */
import successSvg from 'icons/_icon_status_success.svg'; import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg'; import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll'; import simplePoll from '~/lib/utils/simple_poll';
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
...@@ -25,6 +25,9 @@ export default { ...@@ -25,6 +25,9 @@ export default {
warningSvg, warningSvg,
}; };
}, },
components: {
statusIcon,
},
computed: { computed: {
commitMessageLinkTitle() { commitMessageLinkTitle() {
const withDesc = 'Include description in commit message'; const withDesc = 'Include description in commit message';
...@@ -200,7 +203,10 @@ export default { ...@@ -200,7 +203,10 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<status-icon status="success" />
<div class="media-body">
<div class="media space-children">
<span class="btn-group"> <span class="btn-group">
<button <button
@click="handleMergeButtonClick()" @click="handleMergeButtonClick()"
...@@ -217,14 +223,12 @@ export default { ...@@ -217,14 +223,12 @@ export default {
v-if="shouldShowMergeOptionsDropdown" v-if="shouldShowMergeOptionsDropdown"
:disabled="isMergeButtonDisabled" :disabled="isMergeButtonDisabled"
type="button" type="button"
class="btn btn-small btn-info dropdown-toggle" class="btn btn-small btn-info dropdown-toggle js-merge-moment"
data-toggle="dropdown"> data-toggle="dropdown"
aria-label="Select merge moment">
<i <i
class="fa fa-caret-down" class="fa fa-chevron-down"
aria-hidden="true" /> aria-hidden="true" />
<span class="sr-only">
Select merge moment
</span>
</button> </button>
<ul <ul
v-if="shouldShowMergeOptionsDropdown" v-if="shouldShowMergeOptionsDropdown"
...@@ -235,11 +239,13 @@ export default { ...@@ -235,11 +239,13 @@ export default {
@click.prevent="handleMergeButtonClick(true)" @click.prevent="handleMergeButtonClick(true)"
class="merge_when_pipeline_succeeds" class="merge_when_pipeline_succeeds"
href="#"> href="#">
<span class="media">
<span <span
v-html="successSvg" v-html="successSvg"
class="merge-opt-icon" class="merge-opt-icon"
aria-hidden="true"></span> aria-hidden="true"></span>
<span class="merge-opt-title">Merge when pipeline succeeds</span> <span class="media-body merge-opt-title">Merge when pipeline succeeds</span>
</span>
</a> </a>
</li> </li>
<li> <li>
...@@ -247,17 +253,20 @@ export default { ...@@ -247,17 +253,20 @@ export default {
@click.prevent="handleMergeButtonClick(false, true)" @click.prevent="handleMergeButtonClick(false, true)"
class="accept-merge-request" class="accept-merge-request"
href="#"> href="#">
<span class="media">
<span <span
v-html="warningSvg" v-html="warningSvg"
class="merge-opt-icon" class="merge-opt-icon"
aria-hidden="true"></span> aria-hidden="true"></span>
<span class="merge-opt-title">Merge immediately</span> <span class="media-body merge-opt-title">Merge immediately</span>
</span>
</a> </a>
</li> </li>
</ul> </ul>
</span> </span>
<div class="media-body space-children">
<template v-if="isMergeAllowed()"> <template v-if="isMergeAllowed()">
<label class="spacing"> <label>
<input <input
id="remove-source-branch-input" id="remove-source-branch-input"
v-model="removeSourceBranch" v-model="removeSourceBranch"
...@@ -283,7 +292,14 @@ export default { ...@@ -283,7 +292,14 @@ export default {
Modify commit message Modify commit message
</button> </button>
</span> </span>
</template>
<template v-else>
<span class="bold">
The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure
</span>
</template>
</div>
</div>
<div <div
v-if="showCommitMessageEditor" v-if="showCommitMessageEditor"
class="prepend-top-default commit-message-editor"> class="prepend-top-default commit-message-editor">
...@@ -303,7 +319,7 @@ export default { ...@@ -303,7 +319,7 @@ export default {
rows="14" rows="14"
name="Commit message"></textarea> name="Commit message"></textarea>
</div> </div>
<p class="hint">Try to keep the first line under 52 characters and the others under 72.</p> <p class="hint">Try to keep the first line under 52 characters and the others under 72</p>
<div class="hint"> <div class="hint">
<a <a
@click.prevent="updateCommitMessage" @click.prevent="updateCommitMessage"
...@@ -312,12 +328,7 @@ export default { ...@@ -312,12 +328,7 @@ export default {
</div> </div>
</div> </div>
</div> </div>
</template> </div>
<template v-else>
<span class="bold">
The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.
</span>
</template>
</div> </div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetSHAMismatch', name: 'MRWidgetSHAMismatch',
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
The source branch HEAD has recently changed. Please reload the page and review the changes before merging. The source branch HEAD has recently changed. Please reload the page and review the changes before merging
</span> </span>
</div> </div>
</div>
`, `,
}; };
import statusIcon from '../mr_widget_status_icon';
export default { export default {
name: 'MRWidgetUnresolvedDiscussions', name: 'MRWidgetUnresolvedDiscussions',
props: { props: {
mr: { type: Object, required: true }, mr: { type: Object, required: true },
}, },
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" showDisabledButton />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
There are unresolved discussions. Please resolve these discussions There are unresolved discussions. Please resolve these discussions
<span v-if="mr.canCreateIssue">or</span>
<span v-else>.</span>
</span> </span>
<a <a
v-if="mr.createIssueToResolveDiscussionsPath" v-if="mr.createIssueToResolveDiscussionsPath"
...@@ -23,5 +22,6 @@ export default { ...@@ -23,5 +22,6 @@ export default {
Create an issue to resolve them later Create an issue to resolve them later
</a> </a>
</div> </div>
</div>
`, `,
}; };
/* global Flash */ /* global Flash */
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
export default { export default {
...@@ -28,21 +29,21 @@ export default { ...@@ -28,21 +29,21 @@ export default {
}); });
}, },
}, },
components: {
statusIcon,
},
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<button <status-icon status="failed" :showDisabledButton="Boolean(mr.removeWIPPath)" />
type="button" <div class="media-body space-children">
class="btn btn-success btn-small"
disabled="true">
Merge</button>
<span class="bold"> <span class="bold">
This merge request is currently Work In Progress and therefore unable to merge This is a Work in Progress
</span>
<template v-if="mr.removeWIPPath">
<i <i
class="fa fa-question-circle has-tooltip" class="fa fa-question-circle has-tooltip"
title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged." /> title="When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged." />
</span>
<button <button
v-if="mr.removeWIPPath"
@click="removeWIP" @click="removeWIP"
:disabled="isMakingRequest" :disabled="isMakingRequest"
type="button" type="button"
...@@ -53,7 +54,7 @@ export default { ...@@ -53,7 +54,7 @@ export default {
aria-hidden="true" /> aria-hidden="true" />
Resolve WIP status Resolve WIP status
</button> </button>
</template> </div>
</div> </div>
`, `,
}; };
...@@ -35,8 +35,13 @@ import { ...@@ -35,8 +35,13 @@ import {
export default { export default {
el: '#js-vue-mr-widget', el: '#js-vue-mr-widget',
name: 'MRWidget', name: 'MRWidget',
props: {
mrData: {
type: Object,
},
},
data() { data() {
const store = new MRWidgetStore(gl.mrWidgetData); const store = new MRWidgetStore(this.mrData || window.gl.mrWidgetData);
const service = this.createService(store); const service = this.createService(store);
return { return {
mr: store, mr: store,
...@@ -232,14 +237,19 @@ export default { ...@@ -232,14 +237,19 @@ export default {
v-if="shouldRenderDeployments" v-if="shouldRenderDeployments"
:mr="mr" :mr="mr"
:service="service" /> :service="service" />
<div class="mr-widget-section">
<component <component
:is="componentName" :is="componentName"
:mr="mr" :mr="mr"
:service="service" /> :service="service" />
<mr-widget-related-links <mr-widget-related-links
v-if="shouldRenderRelatedLinks" v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks" /> :related-links="mr.relatedLinks" />
<mr-widget-merge-help v-if="shouldRenderMergeHelp" /> </div>
<div class="mr-widget-footer" v-if="shouldRenderMergeHelp">
<mr-widget-merge-help />
</div>
</div> </div>
`, `,
}; };
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
@import 'framework/tw_bootstrap_variables'; @import 'framework/tw_bootstrap_variables';
@import 'framework/tw_bootstrap'; @import 'framework/tw_bootstrap';
@import "framework/layout"; @import "framework/layout";
@import "framework/animations"; @import "framework/animations";
@import "framework/avatar"; @import "framework/avatar";
@import "framework/asciidoctor"; @import "framework/asciidoctor";
...@@ -26,8 +25,10 @@ ...@@ -26,8 +25,10 @@
@import "framework/lists"; @import "framework/lists";
@import "framework/logo"; @import "framework/logo";
@import "framework/markdown_area"; @import "framework/markdown_area";
@import "framework/media_object";
@import "framework/mobile"; @import "framework/mobile";
@import "framework/modal"; @import "framework/modal";
@import "framework/media_object";
@import "framework/nav"; @import "framework/nav";
@import "framework/pagination"; @import "framework/pagination";
@import "framework/panels"; @import "framework/panels";
......
.media {
display: flex;
align-items: flex-start;
}
.media-body {
flex: 1;
}
...@@ -2,10 +2,38 @@ ...@@ -2,10 +2,38 @@
* MR -> show: Automerge widget * MR -> show: Automerge widget
* *
*/ */
$status-icon-size: 22px;
$status-icon-margin: $gl-btn-padding;
.space-children {
@include clearfix;
> * {
float: left;
}
> *:not(:last-child) {
margin-right: 10px;
}
}
.mr-state-widget { .mr-state-widget {
color: $gl-text-color; color: $gl-text-color;
border: 1px solid $border-color; border: 1px solid $border-color;
border-radius: 2px; border-radius: 2px;
line-height: 28px;
.mr-widget-heading,
.mr-widget-section,
.mr-widget-footer {
padding: 16px;
border-top: solid 1px $border-color;
}
.mr-widget-footer {
padding: 0;
}
form { form {
margin-bottom: 0; margin-bottom: 0;
...@@ -15,15 +43,37 @@ ...@@ -15,15 +43,37 @@
} }
} }
label {
margin-bottom: 0;
}
.btn {
font-size: 14px;
&[disabled] {
opacity: 0.3;
}
&.btn-xs {
line-height: 1;
padding: 5px 10px;
margin-top: 1px;
}
&.dropdown-toggle {
padding: 4px 10px;
.fa {
color: inherit;
}
}
}
.accept-merge-holder { .accept-merge-holder {
.accept-action { .accept-action {
display: inline-block; display: inline-block;
float: left; float: left;
.btn-success.dropdown-toggle .fa {
color: inherit;
}
.accept-merge-request { .accept-merge-request {
&.ci-pending, &.ci-pending,
&.ci-running { &.ci-running {
...@@ -40,7 +90,6 @@ ...@@ -40,7 +90,6 @@
} }
.accept-control { .accept-control {
display: inline-block;
float: left; float: left;
margin: 0; margin: 0;
margin-left: 20px; margin-left: 20px;
...@@ -84,77 +133,64 @@ ...@@ -84,77 +133,64 @@
.ci-widget { .ci-widget {
color: $gl-text-color; color: $gl-text-color;
display: -webkit-flex;
display: flex; display: flex;
-webkit-align-items: center;
align-items: center;
padding: $gl-padding-top $gl-padding 0;
svg {
position: relative;
top: 1px;
overflow: visible;
}
> span {
padding-right: 4px;
}
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
flex-wrap: wrap; flex-wrap: wrap;
} }
.icon-link > .ci-status-icon > svg {
width: 22px;
height: 22px;
margin-right: 8px;
} }
.ci-error { .mr-widget-icon {
margin-right: $btn-side-margin; font-size: 22px;
margin-right: $status-icon-margin;
} }
.ci-status-icon svg {
width: $status-icon-size;
height: $status-icon-size;
margin: 3px 0;
position: relative;
overflow: visible;
display: block;
} }
.mr-widget-body, .mr-widget-body {
.mr-widget-footer { @include clearfix;
margin: 16px;
&.media > *:first-child {
margin-right: 10px;
}
} }
.mr-widget-pipeline-graph { .mr-widget-pipeline-graph {
flex-shrink: 0; padding: 0 4px;
.dropdown-menu { .dropdown-menu {
margin-top: 11px;
z-index: 300; z-index: 300;
} }
.ci-action-icon-wrapper { .ci-action-icon-wrapper {
line-height: 16px; line-height: 16px;
} }
@media (max-width: $screen-xs-max) {
order: 1;
margin-top: $gl-padding-top;
border-radius: 3px;
background-color: $white-light;
border: 1px solid $gray-darker;
width: 100%;
text-align: center;
.dropdown-menu {
margin-left: -97.5px;
} }
.arrow-up::before, .mini-pipeline-graph-dropdown-toggle {
.arrow-up::after, { vertical-align: top;
margin-left: 97.5px;
} }
.mini-pipeline-graph-dropdown-menu .mini-pipeline-graph-dropdown-item {
display: flex;
align-items: center;
.ci-status-text,
.ci-status-icon {
top: 0;
margin-right: 10px;
} }
} }
.normal { .normal {
color: $gl-text-color; line-height: 28px;
font-size: 15px;
} }
.capitalize { .capitalize {
...@@ -165,7 +201,7 @@ ...@@ -165,7 +201,7 @@
@extend .ref-name; @extend .ref-name;
color: $gl-text-color; color: $gl-text-color;
font-weight: bold; font-weight: 600;
overflow: hidden; overflow: hidden;
margin: 0 3px; margin: 0 3px;
word-break: break-all; word-break: break-all;
...@@ -189,52 +225,19 @@ ...@@ -189,52 +225,19 @@
} }
} }
.js-deployment-link {
display: inline-block;
}
.mr-widget-help { .mr-widget-help {
margin: $gl-padding; padding: 10px 16px 10px 48px;
color: $ci-skipped-color; font-style: italic;
}
.mr-info-list {
&.mr-links {
margin-left: 28px;
}
&.mr-memory-usage {
margin: 5px 0 10px 25px;
}
}
.mr-widget-heading {
.btn-default.btn-xs {
margin-left: 5px;
}
}
.mr-widget-body {
.btn {
font-size: 15px;
}
.btn-group .btn {
padding: 5px 10px;
&.dropdown-toggle {
padding: 5px 7px;
}
}
} }
.mr-widget-body { .mr-widget-body {
h4 { h4 {
font-weight: bold; float: left;
font-size: 15px; font-weight: 600;
margin: 5px 0; font-size: 14px;
color: $gl-text-color; line-height: inherit;
margin-top: 0;
margin-bottom: 0;
&.has-conflicts .fa-exclamation-triangle { &.has-conflicts .fa-exclamation-triangle {
color: $gl-warning; color: $gl-warning;
...@@ -255,18 +258,16 @@ ...@@ -255,18 +258,16 @@
} }
.spacing { .spacing {
margin: 0 $gl-padding; margin: 0 0 0 10px;
} }
.bold { .bold {
font-weight: bold; font-weight: 600;
font-size: 15px;
color: $gl-gray-light; color: $gl-gray-light;
} }
.state-label { .state-label {
font-size: 16px; font-weight: 600;
font-weight: bold;
padding-right: 10px; padding-right: 10px;
} }
...@@ -274,16 +275,6 @@ ...@@ -274,16 +275,6 @@
color: $gl-danger; color: $gl-danger;
} }
.mr-widget-help {
margin: $gl-padding 0;
}
.with-button {
position: relative;
top: 6px;
margin-bottom: 24px;
}
.spacing, .spacing,
.bold { .bold {
vertical-align: middle; vertical-align: middle;
...@@ -316,34 +307,15 @@ ...@@ -316,34 +307,15 @@
} }
} }
.has-error-message + .has-custom-error {
margin-left: 0;
}
.has-custom-error { .has-custom-error {
display: inline-block; display: inline-block;
margin-left: 70px;
}
.merge-error-text {
margin-left: 70px;
} }
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
h4 {
font-size: 14px;
}
p { p {
font-size: 13px; font-size: 13px;
} }
.btn,
.btn-group,
.accept-action {
margin-bottom: 4px;
}
.btn-grouped { .btn-grouped {
float: none; float: none;
margin-right: 0; margin-right: 0;
...@@ -351,13 +323,6 @@ ...@@ -351,13 +323,6 @@
.accept-action { .accept-action {
width: 100%; width: 100%;
text-align: center;
}
.accept-control {
width: 100%;
text-align: center;
margin: 0;
} }
} }
...@@ -367,19 +332,16 @@ ...@@ -367,19 +332,16 @@
} }
} }
&.mr-state-locked .mr-info-list { &.mr-widget-empty-state {
margin-top: 10px; line-height: 20px;
margin-left: 12px;
}
&.empty-state {
.artwork { .artwork {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
} }
.text { .text {
span { span {
font-weight: bold; font-weight: 600;
} }
p { p {
...@@ -389,10 +351,6 @@ ...@@ -389,10 +351,6 @@
} }
} }
.mr-widget-footer {
border-top: 1px solid $gray-darker;
}
.ci-coverage { .ci-coverage {
float: right; float: right;
} }
...@@ -407,12 +365,6 @@ ...@@ -407,12 +365,6 @@
} }
} }
.mr-state-widget .mr-widget-body {
.approve-btn {
margin-right: 5px;
}
}
.mr_source_commit, .mr_source_commit,
.mr_target_commit { .mr_target_commit {
margin-bottom: 0; margin-bottom: 0;
...@@ -497,8 +449,6 @@ ...@@ -497,8 +449,6 @@
} }
.btn-clipboard { .btn-clipboard {
@extend .pull-right;
margin-right: 20px; margin-right: 20px;
margin-top: 5px; margin-top: 5px;
position: absolute; position: absolute;
...@@ -506,56 +456,29 @@ ...@@ -506,56 +456,29 @@
} }
} }
.mr-links {
padding-left: $status-icon-size + $status-icon-margin;
}
.mr-info-list { .mr-info-list {
clear: left;
position: relative; position: relative;
margin: 10px 0 $gl-padding 12px; padding-top: 4px;
p { p {
margin: 6px 0; margin: 0;
position: relative; position: relative;
padding-left: 15px; padding: 4px 0;
&::before {
content: '';
position: absolute;
border-top: 2px solid $border-color;
height: 1px;
top: 9px;
width: 8px;
left: 0;
}
&:last-child { &:last-child {
margin-bottom: 0; padding-bottom: 0;
} }
} }
.legend {
height: 100%;
width: 2px;
background: $border-color;
position: absolute;
top: -9px;
}
} }
.mr-info-list.mr-memory-usage { .mr-info-list.mr-memory-usage {
.legend {
height: 65%;
top: 0;
@media (max-width: $screen-xs-max) {
height: 20px;
}
}
p { p {
float: left; float: left;
padding-left: 21px;
&::before {
top: 13px;
}
} }
.memory-graph-container { .memory-graph-container {
...@@ -566,11 +489,17 @@ ...@@ -566,11 +489,17 @@
.mr-source-target { .mr-source-target {
background-color: $gray-light; background-color: $gray-light;
border-radius: 3px 3px 0 0; border-radius: $border-radius-default $border-radius-default 0 0;
border-bottom: 1px solid $border-color; padding: $gl-padding-top $gl-padding;
padding: 0 $gl-padding;
margin-bottom: 6px; .pull-right {
line-height: 44px; margin-top: -2px;
}
.btn-clipboard {
margin-left: 0;
padding-left: 0;
}
.dropdown-toggle .fa { .dropdown-toggle .fa {
color: $gl-text-color; color: $gl-text-color;
...@@ -679,14 +608,8 @@ ...@@ -679,14 +608,8 @@
} }
.merged-buttons { .merged-buttons {
margin-top: 20px;
.btn { .btn {
float: left; float: left;
&:not(:last-child) {
margin-right: 10px;
}
} }
} }
...@@ -807,24 +730,9 @@ ...@@ -807,24 +730,9 @@
border-top: 1px solid $well-inner-border; border-top: 1px solid $well-inner-border;
} }
.approvals-body {
@media (max-width: $screen-xs-max) {
text-align: center;
}
}
.approvals-footer { .approvals-footer {
display: flex; display: flex;
.legend {
height: 16px;
top: 0;
}
.approvers-prefix::before {
top: 10px;
}
.approvers-prefix, .approvers-prefix,
.approvers-list { .approvers-list {
display: flex; display: flex;
...@@ -866,51 +774,33 @@ ...@@ -866,51 +774,33 @@
} }
.mr-memory-usage { .mr-memory-usage {
p.usage-info-loading,
p.usage-info-unavailable,
p.usage-info-failed {
margin-bottom: 5px;
}
p.usage-info-loading .usage-info-load-spinner { p.usage-info-loading .usage-info-load-spinner {
margin-right: 10px; margin-right: 10px;
font-size: 16px; font-size: 16px;
} }
}
@media (max-width: $screen-md-min) {
.mr-info-list.mr-memory-usage .legend { .mr-widget-icon {
height: 80%; font-size: 22px;
} margin: 0 10px 0 0;
}
} }
.mr-widget-code-quality { .mr-widget-code-quality {
padding-top: $gl-padding-top; padding-top: $gl-padding-top;
.padding-left {
padding-left: $gl-padding;
}
.ci-status-icon {
vertical-align: sub;
svg {
width: 22px;
height: 22px;
margin-right: 4px;
}
}
.code-quality-container { .code-quality-container {
border-top: 1px solid $gray-darker; border-top: 1px solid $gray-darker;
border-bottom: 1px solid $gray-darker; border-bottom: 1px solid $gray-darker;
padding: $gl-padding-top; padding: $gl-padding-top;
background-color: $gray-light; background-color: $gray-light;
margin: 4px -16px 0;
.mr-widget-code-quality-list { .mr-widget-code-quality-list {
list-style: none; list-style: none;
padding: 0 36px; padding: 4px 36px;
margin: 0; margin: 0;
line-height: $code_line_height;
li.success { li.success {
color: $green-500; color: $green-500;
......
...@@ -247,7 +247,11 @@ ...@@ -247,7 +247,11 @@
position: relative; position: relative;
vertical-align: middle; vertical-align: middle;
height: 22px; height: 22px;
margin: 3px 6px 3px 0; margin: 3px 0;
+ .stage-container {
margin-left: 6px;
}
// Hack to show a button tooltip inline // Hack to show a button tooltip inline
button.has-tooltip + .tooltip { button.has-tooltip + .tooltip {
......
---
title: clean up merge request widget UI
merge_request:
author:
...@@ -70,7 +70,7 @@ export default { ...@@ -70,7 +70,7 @@ export default {
}, },
}, },
template: ` template: `
<div class="approvals-body"> <div class="approvals-body space-children">
<span v-if="showApproveButton" class="approvals-approve-button-wrap"> <span v-if="showApproveButton" class="approvals-approve-button-wrap">
<button <button
:disabled="approving" :disabled="approving"
......
...@@ -65,8 +65,7 @@ export default { ...@@ -65,8 +65,7 @@ export default {
}, },
template: ` template: `
<div v-if="approvedBy.length" class="approved-by-users approvals-footer clearfix mr-info-list"> <div v-if="approvedBy.length" class="approved-by-users approvals-footer clearfix mr-info-list">
<div class="legend"></div> <div class="approvers-prefix space-children">
<div class="approvers-prefix">
<p>Approved by</p> <p>Approved by</p>
<div class="approvers-list"> <div class="approvers-list">
<span v-for="approver in approvedBy"> <span v-for="approver in approvedBy">
...@@ -89,7 +88,7 @@ export default { ...@@ -89,7 +88,7 @@ export default {
<button <button
:disabled="unapproving" :disabled="unapproving"
@click="unapproveMergeRequest" @click="unapproveMergeRequest"
class="btn btn-sm"> class="btn btn-xs">
<i <i
v-if="unapproving" v-if="unapproving"
class="fa fa-spinner fa-spin" class="fa fa-spinner fa-spin"
......
/* global Flash */ /* global Flash */
import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon';
import ApprovalsBody from './approvals_body'; import ApprovalsBody from './approvals_body';
import ApprovalsFooter from './approvals_footer'; import ApprovalsFooter from './approvals_footer';
...@@ -23,6 +24,15 @@ export default { ...@@ -23,6 +24,15 @@ export default {
components: { components: {
'approvals-body': ApprovalsBody, 'approvals-body': ApprovalsBody,
'approvals-footer': ApprovalsFooter, 'approvals-footer': ApprovalsFooter,
statusIcon,
},
computed: {
status() {
if (this.mr.approvals.approvals_left > 0) {
return 'failed';
}
return 'success';
},
}, },
created() { created() {
const flashErrorMessage = 'An error occured while retrieving approval data for this merge request.'; const flashErrorMessage = 'An error occured while retrieving approval data for this merge request.';
...@@ -37,18 +47,23 @@ export default { ...@@ -37,18 +47,23 @@ export default {
template: ` template: `
<div <div
v-if="mr.approvalsRequired" v-if="mr.approvalsRequired"
class="mr-widget-approvals-container mr-widget-body"> class="mr-widget-approvals-container mr-widget-body mr-widget-section media">
<div
v-if="fetchingApprovals"
class="mr-widget-icon">
<i class="fa fa-spinner fa-spin" />
</div>
<status-icon v-else :status="status" />
<div <div
v-show="fetchingApprovals" v-show="fetchingApprovals"
class="mr-approvals-loading-state"> class="mr-approvals-loading-state media-body">
<span class="approvals-loading-text bold"> <span class="approvals-loading-text">
Checking approval status for this merge request. Checking approval status
</span> </span>
<i class="fa fa-spinner fa-spin" />
</div> </div>
<div <div
v-if="!fetchingApprovals" v-if="!fetchingApprovals"
class="approvals-components"> class="approvals-components media-body">
<approvals-body <approvals-body
:mr="mr" :mr="mr"
:service="service" :service="service"
......
<script> <script>
import successIcon from 'icons/_icon_status_success.svg'; import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon';
import errorIcon from 'icons/_icon_status_failed.svg';
import loadingIcon from '~/vue_shared/components/loading_icon.vue'; import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import '~/lib/utils/text_utility'; import '~/lib/utils/text_utility';
import issuesBlock from './mr_widget_code_quality_issues.vue'; import issuesBlock from './mr_widget_code_quality_issues.vue';
...@@ -22,6 +21,7 @@ export default { ...@@ -22,6 +21,7 @@ export default {
components: { components: {
issuesBlock, issuesBlock,
loadingIcon, loadingIcon,
statusIcon,
}, },
data() { data() {
...@@ -34,8 +34,11 @@ export default { ...@@ -34,8 +34,11 @@ export default {
}, },
computed: { computed: {
stateIcon() { status() {
return this.mr.codeclimateMetrics.newIssues.length ? errorIcon : successIcon; if (this.loadingFailed || this.mr.codeclimateMetrics.newIssues.length) {
return 'failed';
}
return 'success';
}, },
hasNoneIssues() { hasNoneIssues() {
...@@ -55,7 +58,7 @@ export default { ...@@ -55,7 +58,7 @@ export default {
let text = []; let text = [];
if (this.hasNoneIssues) { if (this.hasNoneIssues) {
text.push('No changes to code quality.'); text.push('No changes to code quality');
} else if (this.hasIssues) { } else if (this.hasIssues) {
if (newIssues.length) { if (newIssues.length) {
newIssuesText = ` degraded on ${newIssues.length} ${this.pointsText(newIssues)}`; newIssuesText = ` degraded on ${newIssues.length} ${this.pointsText(newIssues)}`;
...@@ -79,8 +82,6 @@ export default { ...@@ -79,8 +82,6 @@ export default {
if (newIssuesText) { if (newIssuesText) {
text.push(newIssuesText); text.push(newIssuesText);
} }
text.push('.');
} }
return text.join(''); return text.join('');
...@@ -128,27 +129,28 @@ export default { ...@@ -128,27 +129,28 @@ export default {
}; };
</script> </script>
<template> <template>
<section class="mr-widget-code-quality"> <section class="mr-widget-code-quality mr-widget-section">
<div <div
v-if="isLoading" v-if="isLoading"
class="padding-left"> class="media">
<div class="mr-widget-icon">
<i <i
class="fa fa-spinner fa-spin" class="fa fa-spinner fa-spin"
aria-hidden="true"> aria-hidden="true">
</i> </i>
Loading codeclimate report. </div>
<div class="media-body">
Loading codeclimate report
</div>
</div> </div>
<div v-else-if="!isLoading && !loadingFailed"> <div
<span v-else-if="!isLoading && !loadingFailed"
class="padding-left ci-status-icon" class="media">
:class="{ <status-icon :status="status" />
'ci-status-icon-failed': mr.codeclimateMetrics.newIssues.length, <div class="media-body space-children">
'ci-status-icon-passed': mr.codeclimateMetrics.newIssues.length === 0 <span class="js-code-text">
}"
v-html="stateIcon">
</span>
<span>
{{codeText}} {{codeText}}
</span> </span>
...@@ -159,6 +161,8 @@ export default { ...@@ -159,6 +161,8 @@ export default {
@click="toggleCollapsed"> @click="toggleCollapsed">
{{collapseText}} {{collapseText}}
</button> </button>
</div>
</div>
<div <div
class="code-quality-container" class="code-quality-container"
...@@ -178,11 +182,13 @@ export default { ...@@ -178,11 +182,13 @@ export default {
:issues="mr.codeclimateMetrics.newIssues" :issues="mr.codeclimateMetrics.newIssues"
/> />
</div> </div>
</div>
<div <div
v-else-if="loadingFailed" v-else-if="loadingFailed"
class="padding-left"> class="media">
Failed to load codeclimate report. <status-icon status="failed" />
<div class="media-body">
Failed to load codeclimate report
</div>
</div> </div>
</section> </section>
</template> </template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import simplePoll from '~/lib/utils/simple_poll'; import simplePoll from '~/lib/utils/simple_poll';
import eventHub from '~/vue_merge_request_widget/event_hub'; import eventHub from '~/vue_merge_request_widget/event_hub';
import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon';
export default { export default {
props: { props: {
...@@ -14,11 +15,28 @@ export default { ...@@ -14,11 +15,28 @@ export default {
required: true, required: true,
}, },
}, },
components: {
statusIcon,
},
data() { data() {
return { return {
isMakingRequest: false, isMakingRequest: false,
}; };
}, },
computed: {
status() {
if (this.mr.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
return 'failed';
}
return 'success';
},
showDisabledButton() {
return ['failed', 'loading'].includes(this.status);
},
},
methods: { methods: {
rebase() { rebase() {
this.isMakingRequest = true; this.isMakingRequest = true;
...@@ -48,38 +66,24 @@ export default { ...@@ -48,38 +66,24 @@ export default {
}, },
}, },
template: ` template: `
<div class="mr-widget-body"> <div class="mr-widget-body media">
<div class="rebase-state-find-class-convention"> <status-icon :status="status" :showDisabledButton="showDisabledButton" />
<div class="rebase-state-find-class-convention media media-body space-children">
<template v-if="mr.rebaseInProgress || isMakingRequest"> <template v-if="mr.rebaseInProgress || isMakingRequest">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
<i Rebase in progress
class="fa fa-spinner fa-spin"
aria-hidden="true" />
Rebase in progress. This merge request is in the process of being rebased.
</span> </span>
</template> </template>
<template v-if="!mr.rebaseInProgress && !mr.canPushToSourceBranch"> <template v-if="!mr.rebaseInProgress && !mr.canPushToSourceBranch">
<button
type="button"
class="btn btn-success btn-small"
disabled="true">
Merge
</button>
<span class="bold"> <span class="bold">
Fast-forward merge is not possible. Fast-forward merge is not possible.
Rebase the source branch onto Rebase the source branch onto
<span class="label-branch">{{mr.targetBranch}}</span> <span class="label-branch">{{mr.targetBranch}}</span>
to allow this merge request to be merged. to allow this merge request to be merged
</span> </span>
</template> </template>
<template v-if="!mr.rebaseInProgress && mr.canPushToSourceBranch && !isMakingRequest"> <template v-if="!mr.rebaseInProgress && mr.canPushToSourceBranch && !isMakingRequest">
<div class="accept-merge-holder clearfix js-toggle-container accept-action"> <div class="accept-merge-holder clearfix js-toggle-container accept-action media space-children">
<button <button
class="btn btn-small btn-reopen btn-success" class="btn btn-small btn-reopen btn-success"
:disabled="isMakingRequest" :disabled="isMakingRequest"
...@@ -93,7 +97,7 @@ export default { ...@@ -93,7 +97,7 @@ export default {
<span class="bold"> <span class="bold">
Fast-forward merge is not possible. Fast-forward merge is not possible.
Rebase the source branch onto the target branch or merge target Rebase the source branch onto the target branch or merge target
branch into source branch to allow this merge request to be merged. branch into source branch to allow this merge request to be merged
</span> </span>
</div> </div>
</template> </template>
......
import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon';
export default { export default {
props: { props: {
mr: { mr: {
...@@ -5,11 +7,15 @@ export default { ...@@ -5,11 +7,15 @@ export default {
required: true, required: true,
}, },
}, },
components: {
statusIcon,
},
template: ` template: `
<div> <div class="media">
<button type="button" class="btn btn-success btn-small" disabled="true">Merge</button> <status-icon status="failed" showDisabledButton />
<div class="media-body">
<span class="bold"> <span class="bold">
Merge requests are read-only in a secondary Geo node. Merge requests are read-only in a secondary Geo node
</span> </span>
<a <a
:href="mr.geoSecondaryHelpPath" :href="mr.geoSecondaryHelpPath"
...@@ -22,5 +28,6 @@ export default { ...@@ -22,5 +28,6 @@ export default {
<i class="fa fa-question-circle"></i> <i class="fa fa-question-circle"></i>
</a> </a>
</div> </div>
</div>
`, `,
}; };
...@@ -40,6 +40,7 @@ export default { ...@@ -40,6 +40,7 @@ export default {
:mr="mr" :mr="mr"
:service="service" :service="service"
/> />
<div class="mr-widget-section">
<component <component
:is="componentName" :is="componentName"
:mr="mr" :mr="mr"
...@@ -47,7 +48,10 @@ export default { ...@@ -47,7 +48,10 @@ export default {
<mr-widget-related-links <mr-widget-related-links
v-if="shouldRenderRelatedLinks" v-if="shouldRenderRelatedLinks"
:related-links="mr.relatedLinks" /> :related-links="mr.relatedLinks" />
<mr-widget-merge-help v-if="shouldRenderMergeHelp" /> </div>
<div class="mr-widget-footer" v-if="shouldRenderMergeHelp">
<mr-widget-merge-help />
</div>
</div> </div>
`, `,
}; };
...@@ -26,17 +26,11 @@ feature 'Merge Request closing issues message', js: true do ...@@ -26,17 +26,11 @@ feature 'Merge Request closing issues message', js: true do
wait_for_requests wait_for_requests
end end
context 'not closing or mentioning any issue' do
it 'does not display closing issue message' do
expect(page).not_to have_css('.mr-widget-footer')
end
end
context 'closing issues but not mentioning any other issue' do context 'closing issues but not mentioning any other issue' do
let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" } let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Closes issues #{issue_1.to_reference} and #{issue_2.to_reference}") expect(page).to have_content("Closes #{issue_1.to_reference} and #{issue_2.to_reference}")
end end
end end
...@@ -44,7 +38,7 @@ feature 'Merge Request closing issues message', js: true do ...@@ -44,7 +38,7 @@ feature 'Merge Request closing issues message', js: true do
let(:merge_request_description) { "Description\n\nRefers to #{issue_1.to_reference} and #{issue_2.to_reference}" } let(:merge_request_description) { "Description\n\nRefers to #{issue_1.to_reference} and #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Issues #{issue_1.to_reference} and #{issue_2.to_reference} are mentioned but will not be closed.") expect(page).to have_content("Mentions #{issue_1.to_reference} and #{issue_2.to_reference}")
end end
end end
...@@ -52,8 +46,8 @@ feature 'Merge Request closing issues message', js: true do ...@@ -52,8 +46,8 @@ feature 'Merge Request closing issues message', js: true do
let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" } let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Closes issue #{issue_1.to_reference}.") expect(page).to have_content("Closes #{issue_1.to_reference}")
expect(page).to have_content("Issue #{issue_2.to_reference} is mentioned but will not be closed.") expect(page).to have_content("Mentions #{issue_2.to_reference}")
end end
end end
...@@ -61,7 +55,7 @@ feature 'Merge Request closing issues message', js: true do ...@@ -61,7 +55,7 @@ feature 'Merge Request closing issues message', js: true do
let(:merge_request_title) { "closing #{issue_1.to_reference}, #{issue_2.to_reference}" } let(:merge_request_title) { "closing #{issue_1.to_reference}, #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Closes issues #{issue_1.to_reference} and #{issue_2.to_reference}") expect(page).to have_content("Closes #{issue_1.to_reference} and #{issue_2.to_reference}")
end end
end end
...@@ -69,7 +63,7 @@ feature 'Merge Request closing issues message', js: true do ...@@ -69,7 +63,7 @@ feature 'Merge Request closing issues message', js: true do
let(:merge_request_title) { "Refers to #{issue_1.to_reference} and #{issue_2.to_reference}" } let(:merge_request_title) { "Refers to #{issue_1.to_reference} and #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Issues #{issue_1.to_reference} and #{issue_2.to_reference} are mentioned but will not be closed.") expect(page).to have_content("Mentions #{issue_1.to_reference} and #{issue_2.to_reference}")
end end
end end
...@@ -77,8 +71,8 @@ feature 'Merge Request closing issues message', js: true do ...@@ -77,8 +71,8 @@ feature 'Merge Request closing issues message', js: true do
let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" } let(:merge_request_title) { "closes #{issue_1.to_reference}\n\n refers to #{issue_2.to_reference}" }
it 'does not display closing issue message' do it 'does not display closing issue message' do
expect(page).to have_content("Closes issue #{issue_1.to_reference}. Issue #{issue_2.to_reference} is mentioned but will not be closed.") expect(page).to have_content("Closes #{issue_1.to_reference}")
expect(page).to have_content("Issue #{issue_2.to_reference} is mentioned but will not be closed.") expect(page).to have_content("Mentions #{issue_2.to_reference}")
end end
end end
...@@ -92,7 +86,7 @@ feature 'Merge Request closing issues message', js: true do ...@@ -92,7 +86,7 @@ feature 'Merge Request closing issues message', js: true do
it 'displays closing issue message exactly one time' do it 'displays closing issue message exactly one time' do
wait_for_requests wait_for_requests
expect(page).to have_content("Closes issues #{issue_1.to_reference} and #{issue_2.to_reference}", count: 1) expect(page).to have_content("Closes #{issue_1.to_reference} and #{issue_2.to_reference}", count: 1)
end end
end end
end end
...@@ -41,8 +41,8 @@ feature 'Merge When Pipeline Succeeds', :js do ...@@ -41,8 +41,8 @@ feature 'Merge When Pipeline Succeeds', :js do
it 'activates the Merge when pipeline succeeds feature' do it 'activates the Merge when pipeline succeeds feature' do
click_button "Merge when pipeline succeeds" click_button "Merge when pipeline succeeds"
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds." expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
expect(page).to have_content "The source branch will not be removed." expect(page).to have_content "The source branch will not be removed"
expect(page).to have_selector ".js-cancel-auto-merge" expect(page).to have_selector ".js-cancel-auto-merge"
visit_merge_request(merge_request) # Needed to refresh the page visit_merge_request(merge_request) # Needed to refresh the page
expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
...@@ -97,11 +97,11 @@ feature 'Merge When Pipeline Succeeds', :js do ...@@ -97,11 +97,11 @@ feature 'Merge When Pipeline Succeeds', :js do
describe 'enabling Merge when pipeline succeeds via dropdown' do describe 'enabling Merge when pipeline succeeds via dropdown' do
it 'activates the Merge when pipeline succeeds feature' do it 'activates the Merge when pipeline succeeds feature' do
click_button 'Select merge moment' find('.js-merge-moment').click
click_link 'Merge when pipeline succeeds' click_link 'Merge when pipeline succeeds'
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds." expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
expect(page).to have_content "The source branch will not be removed." expect(page).to have_content "The source branch will not be removed"
expect(page).to have_link "Cancel automatic merge" expect(page).to have_link "Cancel automatic merge"
end end
end end
......
...@@ -43,7 +43,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t ...@@ -43,7 +43,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
wait_for_requests wait_for_requests
expect(page).to have_button 'Merge when pipeline succeeds' expect(page).to have_button 'Merge when pipeline succeeds'
expect(page).not_to have_button 'Select merge moment' expect(page).not_to have_button '.js-merge-moment'
end end
end end
...@@ -56,7 +56,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t ...@@ -56,7 +56,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
wait_for_requests wait_for_requests
expect(page).to have_css('button[disabled="disabled"]', text: 'Merge') expect(page).to have_css('button[disabled="disabled"]', text: 'Merge')
expect(page).to have_content('Please retry the job or push a new commit to fix the failure.') expect(page).to have_content('Please retry the job or push a new commit to fix the failure')
end end
end end
...@@ -69,7 +69,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t ...@@ -69,7 +69,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
wait_for_requests wait_for_requests
expect(page).not_to have_button 'Merge' expect(page).not_to have_button 'Merge'
expect(page).to have_content('Please retry the job or push a new commit to fix the failure.') expect(page).to have_content('Please retry the job or push a new commit to fix the failure')
end end
end end
...@@ -113,7 +113,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t ...@@ -113,7 +113,7 @@ feature 'Only allow merge requests to be merged if the pipeline succeeds', js: t
expect(page).to have_button 'Merge when pipeline succeeds' expect(page).to have_button 'Merge when pipeline succeeds'
click_button 'Select merge moment' page.find('.js-merge-moment').click
expect(page).to have_content 'Merge immediately' expect(page).to have_content 'Merge immediately'
end end
end end
......
...@@ -31,11 +31,11 @@ describe('Merge Request Code Quality', () => { ...@@ -31,11 +31,11 @@ describe('Merge Request Code Quality', () => {
}); });
it('should render loading indicator', () => { it('should render loading indicator', () => {
expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report.'); expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report');
}); });
}); });
describe('with successfull request', () => { describe('with successful request', () => {
const interceptor = (request, next) => { const interceptor = (request, next) => {
if (request.url === 'head.json') { if (request.url === 'head.json') {
next(request.respondWith(JSON.stringify(headIssues), { next(request.respondWith(JSON.stringify(headIssues), {
...@@ -66,8 +66,8 @@ describe('Merge Request Code Quality', () => { ...@@ -66,8 +66,8 @@ describe('Merge Request Code Quality', () => {
it('should render provided data', (done) => { it('should render provided data', (done) => {
setTimeout(() => { setTimeout(() => {
expect( expect(
vm.$el.querySelector('span:nth-child(2)').textContent.trim(), vm.$el.querySelector('.js-code-text').textContent.trim(),
).toEqual('Code quality improved on 1 point and degraded on 1 point.'); ).toEqual('Code quality improved on 1 point and degraded on 1 point');
done(); done();
}, 0); }, 0);
}); });
...@@ -79,8 +79,8 @@ describe('Merge Request Code Quality', () => { ...@@ -79,8 +79,8 @@ describe('Merge Request Code Quality', () => {
Vue.nextTick(() => { Vue.nextTick(() => {
expect( expect(
vm.$el.querySelector('span:nth-child(2)').textContent.trim(), vm.$el.querySelector('.js-code-text').textContent.trim(),
).toEqual('Code quality improved on 1 point.'); ).toEqual('Code quality improved on 1 point');
done(); done();
}); });
}, 0); }, 0);
...@@ -89,11 +89,10 @@ describe('Merge Request Code Quality', () => { ...@@ -89,11 +89,10 @@ describe('Merge Request Code Quality', () => {
it('should only render information about added issues', (done) => { it('should only render information about added issues', (done) => {
setTimeout(() => { setTimeout(() => {
vm.mr.codeclimateMetrics.resolvedIssues = []; vm.mr.codeclimateMetrics.resolvedIssues = [];
Vue.nextTick(() => { Vue.nextTick(() => {
expect( expect(
vm.$el.querySelector('span:nth-child(2)').textContent.trim(), vm.$el.querySelector('.js-code-text').textContent.trim(),
).toEqual('Code quality degraded on 1 point.'); ).toEqual('Code quality degraded on 1 point');
done(); done();
}); });
}, 0); }, 0);
...@@ -130,7 +129,7 @@ describe('Merge Request Code Quality', () => { ...@@ -130,7 +129,7 @@ describe('Merge Request Code Quality', () => {
}); });
}); });
describe('with empty successfull request', () => { describe('with empty successful request', () => {
const emptyInterceptor = (request, next) => { const emptyInterceptor = (request, next) => {
if (request.url === 'head.json') { if (request.url === 'head.json') {
next(request.respondWith(JSON.stringify([]), { next(request.respondWith(JSON.stringify([]), {
...@@ -161,8 +160,8 @@ describe('Merge Request Code Quality', () => { ...@@ -161,8 +160,8 @@ describe('Merge Request Code Quality', () => {
it('should render provided data', (done) => { it('should render provided data', (done) => {
setTimeout(() => { setTimeout(() => {
expect( expect(
vm.$el.querySelector('span:nth-child(2)').textContent.trim(), vm.$el.querySelector('.js-code-text').textContent.trim(),
).toEqual('No changes to code quality.'); ).toEqual('No changes to code quality');
done(); done();
}, 0); }, 0);
}); });
...@@ -198,7 +197,7 @@ describe('Merge Request Code Quality', () => { ...@@ -198,7 +197,7 @@ describe('Merge Request Code Quality', () => {
it('should render error indicator', (done) => { it('should render error indicator', (done) => {
setTimeout(() => { setTimeout(() => {
expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report.'); expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report');
done(); done();
}, 0); }, 0);
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment'; import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service'; import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import { statusIconEntityMap } from '~/vue_shared/ci_status_icons';
const deploymentMockData = [ const deploymentMockData = [
{ {
...@@ -43,15 +42,6 @@ describe('MRWidgetDeployment', () => { ...@@ -43,15 +42,6 @@ describe('MRWidgetDeployment', () => {
}); });
}); });
describe('computed', () => {
describe('svg', () => {
it('should have the proper SVG icon', () => {
const vm = createComponent(deploymentMockData);
expect(vm.svg).toEqual(statusIconEntityMap.icon_status_success);
});
});
});
describe('methods', () => { describe('methods', () => {
let vm = createComponent(); let vm = createComponent();
const deployment = deploymentMockData[0]; const deployment = deploymentMockData[0];
......
...@@ -52,10 +52,10 @@ const createComponent = () => { ...@@ -52,10 +52,10 @@ const createComponent = () => {
}; };
const messages = { const messages = {
loadingMetrics: 'Loading deployment statistics.', loadingMetrics: 'Loading deployment statistics',
hasMetrics: 'Memory usage unchanged from 0MB to 0MB', hasMetrics: 'Memory usage unchanged from 0MB to 0MB',
loadFailed: 'Failed to load deployment statistics.', loadFailed: 'Failed to load deployment statistics',
metricsUnavailable: 'Deployment statistics are not available currently.', metricsUnavailable: 'Deployment statistics are not available currently',
}; };
describe('MemoryUsage', () => { describe('MemoryUsage', () => {
......
...@@ -83,13 +83,12 @@ describe('MRWidgetPipeline', () => { ...@@ -83,13 +83,12 @@ describe('MRWidgetPipeline', () => {
expect(el.querySelectorAll('.ci-status-icon.ci-status-icon-success').length).toEqual(1); expect(el.querySelectorAll('.ci-status-icon.ci-status-icon-success').length).toEqual(1);
expect(el.querySelector('.pipeline-id').textContent).toContain(`#${pipeline.id}`); expect(el.querySelector('.pipeline-id').textContent).toContain(`#${pipeline.id}`);
expect(el.innerText).toContain('passed'); expect(el.innerText).toContain('passed');
expect(el.innerText).toContain('with stages');
expect(el.querySelector('.pipeline-id').getAttribute('href')).toEqual(pipeline.path); expect(el.querySelector('.pipeline-id').getAttribute('href')).toEqual(pipeline.path);
expect(el.querySelectorAll('.stage-container').length).toEqual(2); expect(el.querySelectorAll('.stage-container').length).toEqual(2);
expect(el.querySelector('.js-ci-error')).toEqual(null); expect(el.querySelector('.js-ci-error')).toEqual(null);
expect(el.querySelector('.js-commit-link').getAttribute('href')).toEqual(pipeline.commit.commit_path); expect(el.querySelector('.js-commit-link').getAttribute('href')).toEqual(pipeline.commit.commit_path);
expect(el.querySelector('.js-commit-link').textContent).toContain(pipeline.commit.short_id); expect(el.querySelector('.js-commit-link').textContent).toContain(pipeline.commit.short_id);
expect(el.querySelector('.js-mr-coverage').textContent).toContain(`Coverage ${pipeline.coverage}%.`); expect(el.querySelector('.js-mr-coverage').textContent).toContain(`Coverage ${pipeline.coverage}%`);
}); });
it('should list single stage', (done) => { it('should list single stage', (done) => {
...@@ -97,7 +96,6 @@ describe('MRWidgetPipeline', () => { ...@@ -97,7 +96,6 @@ describe('MRWidgetPipeline', () => {
Vue.nextTick(() => { Vue.nextTick(() => {
expect(el.querySelectorAll('.stage-container button').length).toEqual(1); expect(el.querySelectorAll('.stage-container button').length).toEqual(1);
expect(el.innerText).toContain('with stage');
done(); done();
}); });
}); });
......
...@@ -55,33 +55,17 @@ describe('MRWidgetRelatedLinks', () => { ...@@ -55,33 +55,17 @@ describe('MRWidgetRelatedLinks', () => {
}; };
const vm = createComponent(data); const vm = createComponent(data);
describe('hasMultipleIssues', () => { describe('closesText', () => {
it('should return true if the given text has multiple issues', () => { it('returns correct text for open merge request', () => {
expect(vm.hasMultipleIssues(data.relatedLinks.closing)).toBeTruthy(); expect(vm.closesText('open')).toEqual('Closes');
}); });
it('should return false if the given text has one issue', () => { it('returns correct text for closed merge request', () => {
expect(vm.hasMultipleIssues(data.relatedLinks.mentioned)).toBeFalsy(); expect(vm.closesText('closed')).toEqual('Did not close');
});
});
describe('issueLabel', () => {
it('should return true if the given text has multiple issues', () => {
expect(vm.issueLabel('closing')).toEqual('issues');
});
it('should return false if the given text has one issue', () => {
expect(vm.issueLabel('mentioned')).toEqual('issue');
});
});
describe('verbLabel', () => {
it('should return true if the given text has multiple issues', () => {
expect(vm.verbLabel('closing')).toEqual('are');
}); });
it('should return false if the given text has one issue', () => { it('returns correct tense for merged request', () => {
expect(vm.verbLabel('mentioned')).toEqual('is'); expect(vm.closesText('merged')).toEqual('Closed');
}); });
}); });
}); });
...@@ -95,8 +79,8 @@ describe('MRWidgetRelatedLinks', () => { ...@@ -95,8 +79,8 @@ describe('MRWidgetRelatedLinks', () => {
}); });
const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim();
expect(content).toContain('Closes issues #23 and #42'); expect(content).toContain('Closes #23 and #42');
expect(content).not.toContain('mentioned'); expect(content).not.toContain('Mentions');
}); });
it('should have only have mentioned issues text', () => { it('should have only have mentioned issues text', () => {
...@@ -106,8 +90,7 @@ describe('MRWidgetRelatedLinks', () => { ...@@ -106,8 +90,7 @@ describe('MRWidgetRelatedLinks', () => {
}, },
}); });
expect(vm.$el.innerText).toContain('issue #7'); expect(vm.$el.innerText).toContain('Mentions #7');
expect(vm.$el.innerText).toContain('is mentioned but will not be closed.');
expect(vm.$el.innerText).not.toContain('Closes'); expect(vm.$el.innerText).not.toContain('Closes');
}); });
...@@ -120,9 +103,8 @@ describe('MRWidgetRelatedLinks', () => { ...@@ -120,9 +103,8 @@ describe('MRWidgetRelatedLinks', () => {
}); });
const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim(); const content = vm.$el.textContent.replace(/\n(\s)+/g, ' ').trim();
expect(content).toContain('Closes issue #7.'); expect(content).toContain('Closes #7');
expect(content).toContain('issues #23 and #42'); expect(content).toContain('Mentions #23 and #42');
expect(content).toContain('are mentioned but will not be closed.');
}); });
it('should have assing issues link', () => { it('should have assing issues link', () => {
......
...@@ -12,7 +12,7 @@ describe('MRWidgetArchived', () => { ...@@ -12,7 +12,7 @@ describe('MRWidgetArchived', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy(); expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy();
expect(el.querySelector('button').disabled).toBeTruthy(); expect(el.querySelector('button').disabled).toBeTruthy();
expect(el.innerText).toContain('This project is archived, write access has been disabled.'); expect(el.innerText).toContain('This project is archived, write access has been disabled');
}); });
}); });
}); });
...@@ -24,8 +24,8 @@ describe('MRWidgetAutoMergeFailed', () => { ...@@ -24,8 +24,8 @@ describe('MRWidgetAutoMergeFailed', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeFalsy();
expect(vm.$el.innerText).toContain('This merge request failed to be merged automatically.'); expect(vm.$el.innerText).toContain('This merge request failed to be merged automatically');
expect(vm.$el.innerText).toContain(mergeError); expect(vm.$el.innerText).toContain(mergeError);
}); });
}); });
......
...@@ -12,7 +12,7 @@ describe('MRWidgetChecking', () => { ...@@ -12,7 +12,7 @@ describe('MRWidgetChecking', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy(); expect(el.querySelector('button').classList.contains('btn-success')).toBeTruthy();
expect(el.querySelector('button').disabled).toBeTruthy(); expect(el.querySelector('button').disabled).toBeTruthy();
expect(el.innerText).toContain('Checking ability to merge automatically.'); expect(el.innerText).toContain('Checking ability to merge automatically');
expect(el.querySelector('i')).toBeDefined(); expect(el.querySelector('i')).toBeDefined();
}); });
}); });
......
...@@ -29,15 +29,16 @@ describe('MRWidgetConflicts', () => { ...@@ -29,15 +29,16 @@ describe('MRWidgetConflicts', () => {
describe('template', () => { describe('template', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
const el = createComponent().$el; const el = createComponent().$el;
const resolveButton = el.querySelectorAll('.btn-group .btn')[0]; const resolveButton = el.querySelector('.js-resolve-conflicts-button');
const mergeLocallyButton = el.querySelectorAll('.btn-group .btn')[1]; const mergeButton = el.querySelector('.mr-widget-body .btn');
const mergeLocallyButton = el.querySelector('.js-merge-locally-button');
expect(el.textContent).toContain('There are merge conflicts.'); expect(el.textContent).toContain('There are merge conflicts');
expect(el.textContent).not.toContain('ask someone with write access'); expect(el.textContent).not.toContain('ask someone with write access');
expect(el.querySelector('.btn-success').disabled).toBeTruthy(); expect(el.querySelector('.btn-success').disabled).toBeTruthy();
expect(el.querySelectorAll('.btn-group .btn').length).toBe(2);
expect(resolveButton.textContent).toContain('Resolve conflicts'); expect(resolveButton.textContent).toContain('Resolve conflicts');
expect(resolveButton.getAttribute('href')).toEqual(path); expect(resolveButton.getAttribute('href')).toEqual(path);
expect(mergeButton.textContent).toContain('Merge');
expect(mergeLocallyButton.textContent).toContain('Merge locally'); expect(mergeLocallyButton.textContent).toContain('Merge locally');
}); });
...@@ -59,8 +60,8 @@ describe('MRWidgetConflicts', () => { ...@@ -59,8 +60,8 @@ describe('MRWidgetConflicts', () => {
it('should not have action buttons', (done) => { it('should not have action buttons', (done) => {
Vue.nextTick(() => { Vue.nextTick(() => {
expect(vm.$el.querySelectorAll('.btn').length).toBe(1); expect(vm.$el.querySelectorAll('.btn').length).toBe(1);
expect(vm.$el.querySelector('a.js-resolve-conflicts-button')).toEqual(null); expect(vm.$el.querySelector('.js-resolve-conflicts-button')).toEqual(null);
expect(vm.$el.querySelector('a.js-merge-locally-button')).toEqual(null); expect(vm.$el.querySelector('.js-merge-locally-button')).toEqual(null);
done(); done();
}); });
}); });
......
...@@ -94,7 +94,7 @@ describe('MRWidgetFailedToMerge', () => { ...@@ -94,7 +94,7 @@ describe('MRWidgetFailedToMerge', () => {
expect(el.querySelector('button').innerText).toContain('Merge'); expect(el.querySelector('button').innerText).toContain('Merge');
expect(el.querySelector('.js-refresh-button').innerText).toContain('Refresh now'); expect(el.querySelector('.js-refresh-button').innerText).toContain('Refresh now');
expect(el.querySelector('.js-refresh-label')).toEqual(null); expect(el.querySelector('.js-refresh-label')).toEqual(null);
expect(el.innerText).not.toContain('Refreshing now...'); expect(el.innerText).not.toContain('Refreshing now');
setTimeout(() => { setTimeout(() => {
expect(el.innerText).toContain('Refreshing in 9 seconds'); expect(el.innerText).toContain('Refreshing in 9 seconds');
done(); done();
...@@ -115,7 +115,7 @@ describe('MRWidgetFailedToMerge', () => { ...@@ -115,7 +115,7 @@ describe('MRWidgetFailedToMerge', () => {
vm.refresh(); vm.refresh();
Vue.nextTick(() => { Vue.nextTick(() => {
expect(el.innerText).not.toContain('Merge failed. Refreshing'); expect(el.innerText).not.toContain('Merge failed. Refreshing');
expect(el.innerText).toContain('Refreshing now...'); expect(el.innerText).toContain('Refreshing now');
}); });
}); });
}); });
......
...@@ -162,10 +162,10 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { ...@@ -162,10 +162,10 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.innerText).toContain('to be merged automatically when the pipeline succeeds.'); expect(el.innerText).toContain('to be merged automatically when the pipeline succeeds');
expect(el.innerText).toContain('The changes will be merged into'); expect(el.innerText).toContain('The changes will be merged into');
expect(el.innerText).toContain(targetBranch); expect(el.innerText).toContain(targetBranch);
expect(el.innerText).toContain('The source branch will not be removed.'); expect(el.innerText).toContain('The source branch will not be removed');
expect(el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge'); expect(el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge');
expect(el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy(); expect(el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
expect(el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch'); expect(el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch');
...@@ -186,8 +186,8 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { ...@@ -186,8 +186,8 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
Vue.nextTick(() => { Vue.nextTick(() => {
const normalizedText = el.innerText.replace(/\s+/g, ' '); const normalizedText = el.innerText.replace(/\s+/g, ' ');
expect(normalizedText).toContain('The source branch will be removed.'); expect(normalizedText).toContain('The source branch will be removed');
expect(normalizedText).not.toContain('The source branch will not be removed.'); expect(normalizedText).not.toContain('The source branch will not be removed');
done(); done();
}); });
}); });
......
...@@ -142,19 +142,19 @@ describe('MRWidgetMerged', () => { ...@@ -142,19 +142,19 @@ describe('MRWidgetMerged', () => {
expect(el.querySelector('.js-mr-widget-author')).toBeDefined(); expect(el.querySelector('.js-mr-widget-author')).toBeDefined();
expect(el.innerText).toContain('The changes were merged into'); expect(el.innerText).toContain('The changes were merged into');
expect(el.innerText).toContain(targetBranch); expect(el.innerText).toContain(targetBranch);
expect(el.innerText).toContain('The source branch has been removed.'); expect(el.innerText).toContain('The source branch has been removed');
expect(el.innerText).toContain('Revert'); expect(el.innerText).toContain('Revert');
expect(el.innerText).toContain('Cherry-pick'); expect(el.innerText).toContain('Cherry-pick');
expect(el.innerText).not.toContain('You can remove source branch now.'); expect(el.innerText).not.toContain('You can remove source branch now');
expect(el.innerText).not.toContain('The source branch is being removed.'); expect(el.innerText).not.toContain('The source branch is being removed');
}); });
it('should not show source branch removed text', (done) => { it('should not show source branch removed text', (done) => {
vm.mr.sourceBranchRemoved = false; vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => { Vue.nextTick(() => {
expect(el.innerText).toContain('You can remove source branch now.'); expect(el.innerText).toContain('You can remove source branch now');
expect(el.innerText).not.toContain('The source branch has been removed.'); expect(el.innerText).not.toContain('The source branch has been removed');
done(); done();
}); });
}); });
...@@ -164,9 +164,9 @@ describe('MRWidgetMerged', () => { ...@@ -164,9 +164,9 @@ describe('MRWidgetMerged', () => {
vm.mr.sourceBranchRemoved = false; vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => { Vue.nextTick(() => {
expect(el.innerText).toContain('The source branch is being removed.'); expect(el.innerText).toContain('The source branch is being removed');
expect(el.innerText).not.toContain('You can remove source branch now.'); expect(el.innerText).not.toContain('You can remove source branch now');
expect(el.innerText).not.toContain('The source branch has been removed.'); expect(el.innerText).not.toContain('The source branch has been removed');
done(); done();
}); });
}); });
......
...@@ -49,7 +49,7 @@ describe('MRWidgetMissingBranch', () => { ...@@ -49,7 +49,7 @@ describe('MRWidgetMissingBranch', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(content).toContain('source branch does not exist.'); expect(content).toContain('source branch does not exist.');
expect(content).toContain('Please restore the source branch or use a different source branch.'); expect(content).toContain('Please restore it or use a different source branch');
}); });
}); });
}); });
...@@ -11,7 +11,7 @@ describe('MRWidgetNotAllowed', () => { ...@@ -11,7 +11,7 @@ describe('MRWidgetNotAllowed', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(vm.$el.innerText).toContain('Ready to be merged automatically.'); expect(vm.$el.innerText).toContain('Ready to be merged automatically.');
expect(vm.$el.innerText).toContain('Ask someone with write access to this repository to merge this request.'); expect(vm.$el.innerText).toContain('Ask someone with write access to this repository to merge this request');
}); });
}); });
}); });
...@@ -10,7 +10,7 @@ describe('MRWidgetPipelineBlocked', () => { ...@@ -10,7 +10,7 @@ describe('MRWidgetPipelineBlocked', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(vm.$el.innerText).toContain('Pipeline blocked. The pipeline for this merge request requires a manual action to proceed.'); expect(vm.$el.innerText).toContain('Pipeline blocked. The pipeline for this merge request requires a manual action to proceed');
}); });
}); });
}); });
...@@ -10,7 +10,7 @@ describe('MRWidgetPipelineFailed', () => { ...@@ -10,7 +10,7 @@ describe('MRWidgetPipelineFailed', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(vm.$el.innerText).toContain('The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure.'); expect(vm.$el.innerText).toContain('The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure');
}); });
}); });
}); });
...@@ -72,7 +72,7 @@ describe('MRWidgetReadyToMerge', () => { ...@@ -72,7 +72,7 @@ describe('MRWidgetReadyToMerge', () => {
const withDesc = 'Include description in commit message'; const withDesc = 'Include description in commit message';
const withoutDesc = "Don't include description in commit message"; const withoutDesc = "Don't include description in commit message";
it('should return message wit description', () => { it('should return message with description', () => {
expect(vm.commitMessageLinkTitle).toEqual(withDesc); expect(vm.commitMessageLinkTitle).toEqual(withDesc);
}); });
......
...@@ -10,7 +10,7 @@ describe('MRWidgetSHAMismatch', () => { ...@@ -10,7 +10,7 @@ describe('MRWidgetSHAMismatch', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging.'); expect(vm.$el.innerText).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging');
}); });
}); });
}); });
...@@ -78,7 +78,7 @@ describe('MRWidgetWIP', () => { ...@@ -78,7 +78,7 @@ describe('MRWidgetWIP', () => {
it('should have correct elements', () => { it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.innerText).toContain('This merge request is currently Work In Progress and therefore unable to merge'); expect(el.innerText).toContain('This is a Work in Progress');
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy(); expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge'); expect(el.querySelector('button').innerText).toContain('Merge');
expect(el.querySelector('.js-remove-wip').innerText).toContain('Resolve WIP status'); expect(el.querySelector('.js-remove-wip').innerText).toContain('Resolve WIP status');
......
...@@ -30,6 +30,7 @@ export default { ...@@ -30,6 +30,7 @@ export default {
"merge_user_id": null, "merge_user_id": null,
"merge_when_pipeline_succeeds": false, "merge_when_pipeline_succeeds": false,
"source_branch": "daaaa", "source_branch": "daaaa",
"source_branch_link": "daaaa",
"source_project_id": 19, "source_project_id": 19,
"target_branch": "master", "target_branch": "master",
"target_project_id": 19, "target_project_id": 19,
......
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