Merge branch '44296-commit-path' into 'master'

Resolve "Cannot read property 'commit_path' of null"

Closes #44296

See merge request gitlab-org/gitlab-ce!18231
This commit is contained in:
Phil Hughes 2018-04-09 15:27:09 +00:00
commit 9e13ca6a3a
3 changed files with 104 additions and 49 deletions

View file

@ -1,56 +1,61 @@
<script>
/* eslint-disable vue/require-default-prop */
import pipelineStage from '~/pipelines/components/stage.vue';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
import icon from '~/vue_shared/components/icon.vue';
/* eslint-disable vue/require-default-prop */
import PipelineStage from '~/pipelines/components/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
export default {
name: 'MRWidgetPipeline',
components: {
pipelineStage,
ciIcon,
icon,
export default {
name: 'MRWidgetPipeline',
components: {
PipelineStage,
CiIcon,
Icon,
},
props: {
pipeline: {
type: Object,
required: true,
},
props: {
pipeline: {
type: Object,
required: true,
},
// This prop needs to be camelCase, html attributes are case insensive
// https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
hasCi: {
type: Boolean,
required: false,
},
ciStatus: {
type: String,
required: false,
},
// This prop needs to be camelCase, html attributes are case insensive
// https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
hasCi: {
type: Boolean,
required: false,
},
computed: {
hasPipeline() {
return this.pipeline && Object.keys(this.pipeline).length > 0;
},
hasCIError() {
return this.hasCi && !this.ciStatus;
},
status() {
return this.pipeline.details &&
this.pipeline.details.status ? this.pipeline.details.status : {};
},
hasStages() {
return this.pipeline.details &&
this.pipeline.details.stages &&
this.pipeline.details.stages.length;
},
ciStatus: {
type: String,
required: false,
},
};
},
computed: {
hasPipeline() {
return this.pipeline && Object.keys(this.pipeline).length > 0;
},
hasCIError() {
return this.hasCi && !this.ciStatus;
},
status() {
return this.pipeline.details && this.pipeline.details.status
? this.pipeline.details.status
: {};
},
hasStages() {
return (
this.pipeline.details && this.pipeline.details.stages && this.pipeline.details.stages.length
);
},
hasCommitInfo() {
return this.pipeline.commit && Object.keys(this.pipeline.commit).length > 0;
},
},
};
</script>
<template>
<div
v-if="hasPipeline || hasCIError"
class="mr-widget-heading">
class="mr-widget-heading"
>
<div class="ci-widget media">
<template v-if="hasCIError">
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-10">
@ -77,13 +82,17 @@
#{{ pipeline.id }}
</a>
{{ pipeline.details.status.label }} for
{{ pipeline.details.status.label }}
<a
:href="pipeline.commit.commit_path"
class="commit-sha js-commit-link"
>
{{ pipeline.commit.short_id }}</a>.
<template v-if="hasCommitInfo">
for
<a
:href="pipeline.commit.commit_path"
class="commit-sha js-commit-link"
>
{{ pipeline.commit.short_id }}</a>.
</template>
<span class="mr-widget-pipeline-graph">
<span

View file

@ -0,0 +1,6 @@
---
title: Verifiy if pipeline has commit idetails and render information in MR widget
when branch is deleted
merge_request:
author:
type: fixed

View file

@ -113,6 +113,46 @@ describe('MRWidgetPipeline', () => {
});
});
describe('without commit path', () => {
beforeEach(() => {
const mockCopy = Object.assign({}, mockData);
delete mockCopy.pipeline.commit;
vm = mountComponent(Component, {
pipeline: mockCopy.pipeline,
hasCi: true,
ciStatus: 'success',
});
});
it('should render pipeline ID', () => {
expect(
vm.$el.querySelector('.pipeline-id').textContent.trim(),
).toEqual(`#${mockData.pipeline.id}`);
});
it('should render pipeline status', () => {
expect(
vm.$el.querySelector('.media-body').textContent.trim(),
).toContain(mockData.pipeline.details.status.label);
expect(
vm.$el.querySelector('.js-commit-link'),
).toBeNull();
});
it('should render pipeline graph', () => {
expect(vm.$el.querySelector('.mr-widget-pipeline-graph')).toBeDefined();
expect(vm.$el.querySelectorAll('.stage-container').length).toEqual(mockData.pipeline.details.stages.length);
});
it('should render coverage information', () => {
expect(
vm.$el.querySelector('.media-body').textContent,
).toContain(`Coverage ${mockData.pipeline.coverage}`);
});
});
describe('without coverage', () => {
it('should not render a coverage', () => {
const mockCopy = Object.assign({}, mockData);