Commit 49f3b36e authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch 'follow-up-move-statuses-to-new-component' into 'master'

Follow up: Move compliance dashboard statuses to new component

See merge request gitlab-org/gitlab!37230
parents 0f1ea152 a0080239
<script> <script>
import { GlTooltipDirective } from '@gitlab/ui'; import { GlTooltipDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago'; import timeagoMixin from '~/vue_shared/mixins/timeago';
import ApprovalStatus from './approval_status.vue';
import Approvers from './approvers.vue'; import Approvers from './approvers.vue';
import BranchDetails from './branch_details.vue'; import BranchDetails from './branch_details.vue';
import MergeRequest from './merge_request.vue';
import PipelineStatus from './pipeline_status.vue';
import GridColumnHeading from '../shared/grid_column_heading.vue'; import GridColumnHeading from '../shared/grid_column_heading.vue';
import MergeRequest from './merge_request.vue';
import Pagination from '../shared/pagination.vue'; import Pagination from '../shared/pagination.vue';
import Status from './status.vue';
export default { export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
components: { components: {
ApprovalStatus,
Approvers, Approvers,
BranchDetails, BranchDetails,
GridColumnHeading, GridColumnHeading,
MergeRequest, MergeRequest,
PipelineStatus,
Pagination, Pagination,
Status,
}, },
mixins: [timeagoMixin], mixins: [timeagoMixin],
props: { props: {
...@@ -50,9 +47,6 @@ export default { ...@@ -50,9 +47,6 @@ export default {
timeTooltip(mergedAt) { timeTooltip(mergedAt) {
return this.tooltipTitle(mergedAt); return this.tooltipTitle(mergedAt);
}, },
hasStatus(status) {
return !isEmpty(status);
},
hasBranchDetails(mergeRequest) { hasBranchDetails(mergeRequest) {
return mergeRequest.target_branch && mergeRequest.source_branch; return mergeRequest.target_branch && mergeRequest.source_branch;
}, },
...@@ -86,24 +80,15 @@ export default { ...@@ -86,24 +80,15 @@ export default {
:merge-request="mergeRequest" :merge-request="mergeRequest"
/> />
<div <status
:key="key(mergeRequest.id, $options.keyTypes.approvalStatus)" :key="key(mergeRequest.id, 'approval')"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5" :status="{ type: 'approval', data: mergeRequest.approval_status }"
> />
<approval-status
v-if="hasStatus(mergeRequest.approval_status)" <status
:status="mergeRequest.approval_status" :key="key(mergeRequest.id, 'pipeline')"
/> :status="{ type: 'pipeline', data: mergeRequest.pipeline_status }"
</div> />
<div
:key="key(mergeRequest.id, $options.keyTypes.pipeline)"
class="dashboard-pipeline gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5"
>
<pipeline-status
v-if="hasStatus(mergeRequest.pipeline_status)"
:status="mergeRequest.pipeline_status"
/>
</div>
<div <div
:key="key(mergeRequest.id, $options.keyTypes.updates)" :key="key(mergeRequest.id, $options.keyTypes.updates)"
......
<script>
import { isEmpty } from 'lodash';
import Approval from './statuses/approval.vue';
import Pipeline from './statuses/pipeline.vue';
export default {
components: {
Approval,
Pipeline,
},
props: {
status: {
type: Object,
required: true,
},
},
computed: {
hasData() {
return !isEmpty(this.status.data);
},
},
};
</script>
<template>
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5"
>
<component :is="status.type" v-if="hasData" :status="status.data" />
</div>
</template>
...@@ -28,13 +28,11 @@ export default { ...@@ -28,13 +28,11 @@ export default {
return `status_${this.status}`; return `status_${this.status}`;
}, },
group() { group() {
const { status } = this; if (this.status === 'warning') {
if (status === 'warning') {
return APPROVAL_WARNING_ICON; return APPROVAL_WARNING_ICON;
} }
return status; return this.status;
}, },
}, },
tooltips: { tooltips: {
......
<script> <script>
import { GlTooltipDirective } from '@gitlab/ui'; import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
...@@ -10,6 +10,7 @@ export default { ...@@ -10,6 +10,7 @@ export default {
}, },
components: { components: {
CiIcon, CiIcon,
GlLink,
}, },
props: { props: {
status: { status: {
...@@ -31,7 +32,7 @@ export default { ...@@ -31,7 +32,7 @@ export default {
</script> </script>
<template> <template>
<a :href="pipelineCiStatus.details_path"> <gl-link :href="pipelineCiStatus.details_path">
<ci-icon v-gl-tooltip.left="pipelineTitle" class="gl-display-flex" :status="pipelineCiStatus" /> <ci-icon v-gl-tooltip.left="pipelineTitle" class="gl-display-flex" :status="pipelineCiStatus" />
</a> </gl-link>
</template> </template>
...@@ -30,17 +30,13 @@ exports[`MergeRequestsGrid component when intialized matches the snapshot 1`] = ...@@ -30,17 +30,13 @@ exports[`MergeRequestsGrid component when intialized matches the snapshot 1`] =
Merge request 0 Merge request 0
</div> </div>
<div <status-stub
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5" status="[object Object]"
> />
<!---->
</div>
<div <status-stub
class="dashboard-pipeline gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5" status="[object Object]"
> />
<!---->
</div>
<div <div
class="gl-text-right gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5 gl-relative" class="gl-text-right gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5 gl-relative"
...@@ -65,17 +61,13 @@ exports[`MergeRequestsGrid component when intialized matches the snapshot 1`] = ...@@ -65,17 +61,13 @@ exports[`MergeRequestsGrid component when intialized matches the snapshot 1`] =
Merge request 1 Merge request 1
</div> </div>
<div <status-stub
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5" status="[object Object]"
> />
<!---->
</div>
<div <status-stub
class="dashboard-pipeline gl-display-flex gl-align-items-center gl-justify-content-center gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5" status="[object Object]"
> />
<!---->
</div>
<div <div
class="gl-text-right gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5 gl-relative" class="gl-text-right gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5 gl-relative"
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import MergeRequestsGrid from 'ee/compliance_dashboard/components/merge_requests/grid.vue';
import ApprovalStatus from 'ee/compliance_dashboard/components/merge_requests/approval_status.vue';
import BranchDetails from 'ee/compliance_dashboard/components/merge_requests/branch_details.vue';
import PipelineStatus from 'ee/compliance_dashboard/components/merge_requests/pipeline_status.vue';
import Approvers from 'ee/compliance_dashboard/components/merge_requests/approvers.vue'; import Approvers from 'ee/compliance_dashboard/components/merge_requests/approvers.vue';
import { createMergeRequests, createPipelineStatus } from '../../mock_data'; import BranchDetails from 'ee/compliance_dashboard/components/merge_requests/branch_details.vue';
import MergeRequestsGrid from 'ee/compliance_dashboard/components/merge_requests/grid.vue';
import Status from 'ee/compliance_dashboard/components/merge_requests/status.vue';
import { createMergeRequests } from '../../mock_data';
describe('MergeRequestsGrid component', () => { describe('MergeRequestsGrid component', () => {
let wrapper; let wrapper;
const findMergeRequests = () => wrapper.findAll('[data-testid="merge-request"]'); const findMergeRequests = () => wrapper.findAll('[data-testid="merge-request"]');
const findTime = () => wrapper.find('time'); const findTime = () => wrapper.find('time');
const findApprovalStatus = () => wrapper.find(ApprovalStatus); const findStatuses = () => wrapper.findAll(Status);
const findPipelineStatus = () => wrapper.find(PipelineStatus);
const findApprovers = () => wrapper.find(Approvers); const findApprovers = () => wrapper.find(Approvers);
const findBranchDetails = () => wrapper.find(BranchDetails); const findBranchDetails = () => wrapper.find(BranchDetails);
const createComponent = (mergeRequestProps = {}) => { const createComponent = (mergeRequests = {}) => {
return shallowMount(MergeRequestsGrid, { return shallowMount(MergeRequestsGrid, {
propsData: { propsData: {
mergeRequests: createMergeRequests({ count: 2, props: mergeRequestProps }), mergeRequests,
isLastPage: false, isLastPage: false,
}, },
stubs: { stubs: {
...@@ -38,7 +37,7 @@ describe('MergeRequestsGrid component', () => { ...@@ -38,7 +37,7 @@ describe('MergeRequestsGrid component', () => {
describe('when intialized', () => { describe('when intialized', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent(createMergeRequests({ count: 2, props: {} }));
}); });
it('matches the snapshot', () => { it('matches the snapshot', () => {
...@@ -46,28 +45,28 @@ describe('MergeRequestsGrid component', () => { ...@@ -46,28 +45,28 @@ describe('MergeRequestsGrid component', () => {
}); });
it('renders a list of merge requests', () => { it('renders a list of merge requests', () => {
expect(findMergeRequests().length).toBe(2); expect(findMergeRequests()).toHaveLength(2);
}); });
describe('approval status', () => { it('passes the correct props to the statuses', () => {
it('does not render if there is no approval status', () => { const mergeRequest = createMergeRequests({ count: 1 });
expect(findApprovalStatus().exists()).toBe(false); wrapper = createComponent(mergeRequest);
});
it('renders if there is an approval status', () => { findStatuses().wrappers.forEach(status => {
wrapper = createComponent({ approval_status: 'success' }); const { type, data } = status.props('status');
expect(findApprovalStatus().exists()).toBe(true);
});
});
describe('pipeline status', () => { switch (type) {
it('does not render if there is no pipeline', () => { case 'pipeline':
expect(findPipelineStatus().exists()).toBe(false); expect(data).toEqual(mergeRequest[0].pipeline_status);
}); break;
case 'approval':
expect(data).toEqual(mergeRequest[0].approval_status);
break;
it('renders if there is a pipeline', () => { default:
wrapper = createComponent({ pipeline_status: createPipelineStatus('success') }); throw new Error('Unknown status type');
expect(findPipelineStatus().exists()).toBe(true); }
}); });
}); });
...@@ -77,7 +76,12 @@ describe('MergeRequestsGrid component', () => { ...@@ -77,7 +76,12 @@ describe('MergeRequestsGrid component', () => {
}); });
it('renders if there are branch details', () => { it('renders if there are branch details', () => {
wrapper = createComponent({ target_branch: 'master', source_branch: 'feature' }); wrapper = createComponent(
createMergeRequests({
count: 2,
props: { target_branch: 'master', source_branch: 'feature' },
}),
);
expect(findBranchDetails().exists()).toBe(true); expect(findBranchDetails().exists()).toBe(true);
}); });
}); });
......
import { shallowMount } from '@vue/test-utils';
import Status from 'ee/compliance_dashboard/components/merge_requests/status.vue';
import Approval from 'ee/compliance_dashboard/components/merge_requests/statuses/approval.vue';
import Pipeline from 'ee/compliance_dashboard/components/merge_requests/statuses/pipeline.vue';
describe('Status component', () => {
let wrapper;
const createComponent = status => {
return shallowMount(Status, {
propsData: { status },
});
};
const checkStatusComponentExists = (status, exists) => {
switch (status.type) {
case 'approval':
return expect(wrapper.find(Approval).exists()).toBe(exists);
case 'pipeline':
return expect(wrapper.find(Pipeline).exists()).toBe(exists);
default:
throw new Error(`Unknown status type: ${status.type}`);
}
};
afterEach(() => {
wrapper.destroy();
});
describe('rendering', () => {
it.each`
type | data
${'approval'} | ${null}
${'approval'} | ${''}
${'pipeline'} | ${{}}
`('does not render if given the status $value', status => {
wrapper = createComponent(status);
checkStatusComponentExists(status, false);
});
it.each`
type | data
${'approval'} | ${'success'}
${'pipeline'} | ${{ group: 'warning' }}
`('renders if given the status $value', status => {
wrapper = createComponent(status);
checkStatusComponentExists(status, true);
});
});
});
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui'; import { GlLink } from '@gitlab/ui';
import ApprovalStatus from 'ee/compliance_dashboard/components/merge_requests/approval_status.vue'; import Approval from 'ee/compliance_dashboard/components/merge_requests/statuses/approval.vue';
describe('ApprovalStatus component', () => { describe('ApprovalStatus component', () => {
let wrapper; let wrapper;
...@@ -10,7 +10,7 @@ describe('ApprovalStatus component', () => { ...@@ -10,7 +10,7 @@ describe('ApprovalStatus component', () => {
const findLink = () => wrapper.find(GlLink); const findLink = () => wrapper.find(GlLink);
const createComponent = status => { const createComponent = status => {
return shallowMount(ApprovalStatus, { return shallowMount(Approval, {
propsData: { status }, propsData: { status },
stubs: { stubs: {
CiIcon: { CiIcon: {
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import PipelineStatus from 'ee/compliance_dashboard/components/merge_requests/pipeline_status.vue'; import Pipeline from 'ee/compliance_dashboard/components/merge_requests/statuses/pipeline.vue';
import { createPipelineStatus } from '../../mock_data'; import { createPipelineStatus } from '../../../mock_data';
describe('PipelineStatus component', () => { describe('Pipeline component', () => {
let wrapper; let wrapper;
const findCiIcon = () => wrapper.find('.ci-icon'); const findCiIcon = () => wrapper.find('.ci-icon');
const findCiLink = () => wrapper.find('a'); const findCiLink = () => wrapper.find(GlLink);
const createComponent = status => { const createComponent = status => {
return shallowMount(PipelineStatus, { return shallowMount(Pipeline, {
propsData: { status }, propsData: { status },
stubs: { stubs: {
CiIcon: { CiIcon: {
......
...@@ -13,6 +13,18 @@ const createUser = id => ({ ...@@ -13,6 +13,18 @@ const createUser = id => ({
web_url: `http://localhost:3000/user-${id}`, web_url: `http://localhost:3000/user-${id}`,
}); });
export const createPipelineStatus = status => ({
details_path: '/h5bp/html5-boilerplate/pipelines/58',
favicon: '',
group: status,
has_details: true,
icon: `status_${status}`,
illustration: null,
label: status,
text: status,
tooltip: status,
});
export const createMergeRequest = ({ id = 1, props } = {}) => { export const createMergeRequest = ({ id = 1, props } = {}) => {
const mergeRequest = { const mergeRequest = {
id, id,
...@@ -22,25 +34,14 @@ export const createMergeRequest = ({ id = 1, props } = {}) => { ...@@ -22,25 +34,14 @@ export const createMergeRequest = ({ id = 1, props } = {}) => {
milestone: null, milestone: null,
path: `/h5bp/html5-boilerplate/-/merge_requests/${id}`, path: `/h5bp/html5-boilerplate/-/merge_requests/${id}`,
title: `Merge request ${id}`, title: `Merge request ${id}`,
author: createUser(id),
pipeline_status: createPipelineStatus('success'),
approval_status: 'success',
}; };
mergeRequest.author = createUser(id);
return { ...mergeRequest, ...props }; return { ...mergeRequest, ...props };
}; };
export const createPipelineStatus = status => ({
details_path: '/h5bp/html5-boilerplate/pipelines/58',
favicon: '',
group: status,
has_details: true,
icon: `status_${status}`,
illustration: null,
label: status,
text: status,
tooltip: status,
});
export const createApprovers = count => { export const createApprovers = count => {
return Array(count) return Array(count)
.fill() .fill()
......
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