Merge branch 'mr-widget-deployment-styling' into 'master'
Fix styling of multiple environments in merge request widget Closes #40610 See merge request gitlab-org/gitlab-ce!17663
This commit is contained in:
commit
1b48285801
9 changed files with 393 additions and 345 deletions
|
@ -0,0 +1,144 @@
|
|||
<script>
|
||||
import timeagoMixin from '../../vue_shared/mixins/timeago';
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import LoadingButton from '../../vue_shared/components/loading_button.vue';
|
||||
import { visitUrl } from '../../lib/utils/url_utility';
|
||||
import createFlash from '../../flash';
|
||||
import MemoryUsage from './memory_usage.vue';
|
||||
import StatusIcon from './mr_widget_status_icon.vue';
|
||||
import MRWidgetService from '../services/mr_widget_service';
|
||||
|
||||
export default {
|
||||
name: 'Deployment',
|
||||
components: {
|
||||
LoadingButton,
|
||||
MemoryUsage,
|
||||
StatusIcon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
mixins: [
|
||||
timeagoMixin,
|
||||
],
|
||||
props: {
|
||||
deployment: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isStopping: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
deployTimeago() {
|
||||
return this.timeFormated(this.deployment.deployed_at);
|
||||
},
|
||||
hasExternalUrls() {
|
||||
return !!(this.deployment.external_url && this.deployment.external_url_formatted);
|
||||
},
|
||||
hasDeploymentTime() {
|
||||
return !!(this.deployment.deployed_at && this.deployment.deployed_at_formatted);
|
||||
},
|
||||
hasDeploymentMeta() {
|
||||
return !!(this.deployment.url && this.deployment.name);
|
||||
},
|
||||
hasMetrics() {
|
||||
return !!(this.deployment.metrics_url);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
stopEnvironment() {
|
||||
const msg = 'Are you sure you want to stop this environment?';
|
||||
const isConfirmed = confirm(msg); // eslint-disable-line
|
||||
|
||||
if (isConfirmed) {
|
||||
this.isStopping = true;
|
||||
|
||||
MRWidgetService.stopEnvironment(this.deployment.stop_url)
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
if (data.redirect_url) {
|
||||
visitUrl(data.redirect_url);
|
||||
}
|
||||
|
||||
this.isStopping = false;
|
||||
})
|
||||
.catch(() => {
|
||||
createFlash('Something went wrong while stopping this environment. Please try again.');
|
||||
this.isStopping = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mr-widget-heading deploy-heading">
|
||||
<div class="ci-widget media">
|
||||
<div class="ci-status-icon ci-status-icon-success">
|
||||
<span class="js-icon-link icon-link">
|
||||
<status-icon status="success" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<div class="deploy-body">
|
||||
<template v-if="hasDeploymentMeta">
|
||||
<span>
|
||||
Deployed to
|
||||
</span>
|
||||
<a
|
||||
:href="deployment.url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
class="deploy-link js-deploy-meta"
|
||||
>
|
||||
{{ deployment.name }}
|
||||
</a>
|
||||
</template>
|
||||
<template v-if="hasExternalUrls">
|
||||
<span>
|
||||
on
|
||||
</span>
|
||||
<a
|
||||
:href="deployment.external_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
class="deploy-link js-deploy-url"
|
||||
>
|
||||
<i
|
||||
class="fa fa-external-link"
|
||||
aria-hidden="true"
|
||||
>
|
||||
</i>
|
||||
{{ deployment.external_url_formatted }}
|
||||
</a>
|
||||
</template>
|
||||
<span
|
||||
v-if="hasDeploymentTime"
|
||||
v-tooltip
|
||||
:title="deployment.deployed_at_formatted"
|
||||
class="js-deploy-time"
|
||||
>
|
||||
{{ deployTimeago }}
|
||||
</span>
|
||||
<loading-button
|
||||
v-if="deployment.stop_url"
|
||||
container-class="btn btn-default btn-xs prepend-left-default"
|
||||
label="Stop environment"
|
||||
:loading="isStopping"
|
||||
@click="stopEnvironment"
|
||||
/>
|
||||
</div>
|
||||
<memory-usage
|
||||
v-if="hasMetrics"
|
||||
:metrics-url="deployment.metrics_url"
|
||||
:metrics-monitoring-url="deployment.metrics_monitoring_url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,113 +0,0 @@
|
|||
import { getTimeago } from '~/lib/utils/datetime_utility';
|
||||
import { visitUrl } from '../../lib/utils/url_utility';
|
||||
import Flash from '../../flash';
|
||||
import MemoryUsage from './memory_usage.vue';
|
||||
import StatusIcon from './mr_widget_status_icon.vue';
|
||||
import MRWidgetService from '../services/mr_widget_service';
|
||||
|
||||
export default {
|
||||
name: 'MRWidgetDeployment',
|
||||
props: {
|
||||
mr: { type: Object, required: true },
|
||||
service: { type: Object, required: true },
|
||||
},
|
||||
components: {
|
||||
MemoryUsage,
|
||||
StatusIcon,
|
||||
},
|
||||
methods: {
|
||||
formatDate(date) {
|
||||
return getTimeago().format(date);
|
||||
},
|
||||
hasExternalUrls(deployment = {}) {
|
||||
return deployment.external_url && deployment.external_url_formatted;
|
||||
},
|
||||
hasDeploymentTime(deployment = {}) {
|
||||
return deployment.deployed_at && deployment.deployed_at_formatted;
|
||||
},
|
||||
hasDeploymentMeta(deployment = {}) {
|
||||
return deployment.url && deployment.name;
|
||||
},
|
||||
stopEnvironment(deployment) {
|
||||
const msg = 'Are you sure you want to stop this environment?';
|
||||
const isConfirmed = confirm(msg); // eslint-disable-line
|
||||
|
||||
if (isConfirmed) {
|
||||
MRWidgetService.stopEnvironment(deployment.stop_url)
|
||||
.then(res => res.data)
|
||||
.then((data) => {
|
||||
if (data.redirect_url) {
|
||||
visitUrl(data.redirect_url);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
new Flash('Something went wrong while stopping this environment. Please try again.'); // eslint-disable-line
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class="mr-widget-heading deploy-heading">
|
||||
<div v-for="deployment in mr.deployments">
|
||||
<div class="ci-widget media">
|
||||
<div class="ci-status-icon ci-status-icon-success">
|
||||
<span class="js-icon-link icon-link">
|
||||
<status-icon status="success" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="media-body space-children">
|
||||
<span>
|
||||
<span
|
||||
v-if="hasDeploymentMeta(deployment)">
|
||||
Deployed to
|
||||
</span>
|
||||
<a
|
||||
v-if="hasDeploymentMeta(deployment)"
|
||||
:href="deployment.url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
class="js-deploy-meta inline">
|
||||
{{deployment.name}}
|
||||
</a>
|
||||
<span
|
||||
v-if="hasExternalUrls(deployment)">
|
||||
on
|
||||
</span>
|
||||
<a
|
||||
v-if="hasExternalUrls(deployment)"
|
||||
:href="deployment.external_url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
class="js-deploy-url inline">
|
||||
<i
|
||||
class="fa fa-external-link"
|
||||
aria-hidden="true" />
|
||||
{{deployment.external_url_formatted}}
|
||||
</a>
|
||||
<span
|
||||
v-if="hasDeploymentTime(deployment)"
|
||||
:data-title="deployment.deployed_at_formatted"
|
||||
class="js-deploy-time"
|
||||
data-toggle="tooltip"
|
||||
data-placement="top">
|
||||
{{formatDate(deployment.deployed_at)}}
|
||||
</span>
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
v-if="deployment.stop_url"
|
||||
@click="stopEnvironment(deployment)"
|
||||
class="btn btn-default btn-xs">
|
||||
Stop environment
|
||||
</button>
|
||||
<memory-usage
|
||||
v-if="deployment.metrics_url"
|
||||
:metrics-url="deployment.metrics_url"
|
||||
:metrics-monitoring-url="deployment.metrics_monitoring_url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
|
@ -14,7 +14,7 @@ export { default as SmartInterval } from '~/smart_interval';
|
|||
export { default as WidgetHeader } from './components/mr_widget_header.vue';
|
||||
export { default as WidgetMergeHelp } from './components/mr_widget_merge_help.vue';
|
||||
export { default as WidgetPipeline } from './components/mr_widget_pipeline.vue';
|
||||
export { default as WidgetDeployment } from './components/mr_widget_deployment';
|
||||
export { default as Deployment } from './components/deployment.vue';
|
||||
export { default as WidgetMaintainerEdit } from './components/mr_widget_maintainer_edit.vue';
|
||||
export { default as WidgetRelatedLinks } from './components/mr_widget_related_links.vue';
|
||||
export { default as MergedState } from './components/states/mr_widget_merged.vue';
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
WidgetHeader,
|
||||
WidgetMergeHelp,
|
||||
WidgetPipeline,
|
||||
WidgetDeployment,
|
||||
Deployment,
|
||||
WidgetMaintainerEdit,
|
||||
WidgetRelatedLinks,
|
||||
MergedState,
|
||||
|
@ -67,9 +67,6 @@ export default {
|
|||
shouldRenderRelatedLinks() {
|
||||
return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
|
||||
},
|
||||
shouldRenderDeployments() {
|
||||
return this.mr.deployments.length;
|
||||
},
|
||||
shouldRenderSourceBranchRemovalStatus() {
|
||||
return !this.mr.canRemoveSourceBranch && this.mr.shouldRemoveSourceBranch &&
|
||||
(!this.mr.isNothingToMergeState && !this.mr.isMergedState);
|
||||
|
@ -216,7 +213,7 @@ export default {
|
|||
'mr-widget-header': WidgetHeader,
|
||||
'mr-widget-merge-help': WidgetMergeHelp,
|
||||
'mr-widget-pipeline': WidgetPipeline,
|
||||
'mr-widget-deployment': WidgetDeployment,
|
||||
Deployment,
|
||||
'mr-widget-maintainer-edit': WidgetMaintainerEdit,
|
||||
'mr-widget-related-links': WidgetRelatedLinks,
|
||||
'mr-widget-merged': MergedState,
|
||||
|
@ -250,10 +247,11 @@ export default {
|
|||
:ci-status="mr.ciStatus"
|
||||
:has-ci="mr.hasCI"
|
||||
/>
|
||||
<mr-widget-deployment
|
||||
v-if="shouldRenderDeployments"
|
||||
:mr="mr"
|
||||
:service="service" />
|
||||
<deployment
|
||||
v-for="deployment in mr.deployments"
|
||||
:key="deployment.id"
|
||||
:deployment="deployment"
|
||||
/>
|
||||
<div class="mr-widget-section">
|
||||
<component
|
||||
:is="componentName"
|
||||
|
|
|
@ -718,6 +718,8 @@
|
|||
}
|
||||
|
||||
.mr-memory-usage {
|
||||
width: 100%;
|
||||
|
||||
p.usage-info-loading .usage-info-load-spinner {
|
||||
margin-right: 10px;
|
||||
font-size: 16px;
|
||||
|
@ -727,3 +729,36 @@
|
|||
.fork-sprite {
|
||||
margin-right: -5px;
|
||||
}
|
||||
|
||||
.deploy-heading {
|
||||
.media-body {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.deploy-body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (min-width: $screen-xs) {
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: .3em;
|
||||
}
|
||||
}
|
||||
|
||||
.deploy-link {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 100px;
|
||||
max-width: 150px;
|
||||
|
||||
@media (min-width: $screen-xs) {
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ describe 'Merge request > User sees deployment widget', :js do
|
|||
wait_for_requests
|
||||
|
||||
expect(page).to have_content("Deployed to #{environment.name}")
|
||||
expect(find('.js-deploy-time')['data-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
|
||||
expect(find('.js-deploy-time')['data-original-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
|
||||
end
|
||||
|
||||
context 'with stop action' do
|
||||
|
|
172
spec/javascripts/vue_mr_widget/components/deployment_spec.js
Normal file
172
spec/javascripts/vue_mr_widget/components/deployment_spec.js
Normal file
|
@ -0,0 +1,172 @@
|
|||
import Vue from 'vue';
|
||||
import * as urlUtils from '~/lib/utils/url_utility';
|
||||
import deploymentComponent from '~/vue_merge_request_widget/components/deployment.vue';
|
||||
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
|
||||
import { getTimeago } from '~/lib/utils/datetime_utility';
|
||||
|
||||
const deploymentMockData = {
|
||||
id: 15,
|
||||
name: 'review/diplo',
|
||||
url: '/root/acets-review-apps/environments/15',
|
||||
stop_url: '/root/acets-review-apps/environments/15/stop',
|
||||
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
|
||||
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
|
||||
external_url: 'http://diplo.',
|
||||
external_url_formatted: 'diplo.',
|
||||
deployed_at: '2017-03-22T22:44:42.258Z',
|
||||
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
|
||||
};
|
||||
const createComponent = () => {
|
||||
const Component = Vue.extend(deploymentComponent);
|
||||
|
||||
return new Component({
|
||||
el: document.createElement('div'),
|
||||
propsData: { deployment: { ...deploymentMockData } },
|
||||
});
|
||||
};
|
||||
|
||||
describe('Deployment component', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
describe('computed', () => {
|
||||
describe('deployTimeago', () => {
|
||||
it('return formatted date', () => {
|
||||
const readable = getTimeago().format(deploymentMockData.deployed_at);
|
||||
expect(vm.deployTimeago).toEqual(readable);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasExternalUrls', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasExternalUrls).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no external_url_formatted', () => {
|
||||
vm.deployment.external_url_formatted = null;
|
||||
|
||||
expect(vm.hasExternalUrls).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no external_url', () => {
|
||||
vm.deployment.external_url = null;
|
||||
|
||||
expect(vm.hasExternalUrls).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDeploymentTime', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasDeploymentTime).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no deployed_at', () => {
|
||||
vm.deployment.deployed_at = null;
|
||||
|
||||
expect(vm.hasDeploymentTime).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no deployed_at_formatted', () => {
|
||||
vm.deployment.deployed_at_formatted = null;
|
||||
|
||||
expect(vm.hasDeploymentTime).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDeploymentMeta', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasDeploymentMeta).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no url', () => {
|
||||
vm.deployment.url = null;
|
||||
|
||||
expect(vm.hasDeploymentMeta).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return false when deployment has no name', () => {
|
||||
vm.deployment.name = null;
|
||||
|
||||
expect(vm.hasDeploymentMeta).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
describe('stopEnvironment', () => {
|
||||
const url = '/foo/bar';
|
||||
const returnPromise = () => new Promise((resolve) => {
|
||||
resolve({
|
||||
data: {
|
||||
redirect_url: url,
|
||||
},
|
||||
});
|
||||
});
|
||||
const mockStopEnvironment = () => {
|
||||
vm.stopEnvironment(deploymentMockData);
|
||||
return vm;
|
||||
};
|
||||
|
||||
it('should show a confirm dialog and call service.stopEnvironment when confirmed', (done) => {
|
||||
spyOn(window, 'confirm').and.returnValue(true);
|
||||
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(true));
|
||||
spyOn(urlUtils, 'visitUrl').and.returnValue(true);
|
||||
vm = mockStopEnvironment();
|
||||
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
expect(MRWidgetService.stopEnvironment).toHaveBeenCalledWith(deploymentMockData.stop_url);
|
||||
setTimeout(() => {
|
||||
expect(urlUtils.visitUrl).toHaveBeenCalledWith(url);
|
||||
done();
|
||||
}, 333);
|
||||
});
|
||||
|
||||
it('should show a confirm dialog but should not work if the dialog is rejected', () => {
|
||||
spyOn(window, 'confirm').and.returnValue(false);
|
||||
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(false));
|
||||
vm = mockStopEnvironment();
|
||||
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
expect(MRWidgetService.stopEnvironment).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
let el;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent(deploymentMockData);
|
||||
el = vm.$el;
|
||||
});
|
||||
|
||||
it('renders deployment name', () => {
|
||||
expect(el.querySelector('.js-deploy-meta').getAttribute('href')).toEqual(deploymentMockData.url);
|
||||
expect(el.querySelector('.js-deploy-meta').innerText).toContain(deploymentMockData.name);
|
||||
});
|
||||
|
||||
it('renders external URL', () => {
|
||||
expect(el.querySelector('.js-deploy-url').getAttribute('href')).toEqual(deploymentMockData.external_url);
|
||||
expect(el.querySelector('.js-deploy-url').innerText).toContain(deploymentMockData.external_url_formatted);
|
||||
});
|
||||
|
||||
it('renders stop button', () => {
|
||||
expect(el.querySelector('.btn')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders deployment time', () => {
|
||||
expect(el.querySelector('.js-deploy-time').innerText).toContain(vm.deployTimeago);
|
||||
});
|
||||
|
||||
it('renders metrics component', () => {
|
||||
expect(el.querySelector('.js-mr-memory-usage')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,179 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import * as urlUtils from '~/lib/utils/url_utility';
|
||||
import deploymentComponent from '~/vue_merge_request_widget/components/mr_widget_deployment';
|
||||
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
|
||||
import { getTimeago } from '~/lib/utils/datetime_utility';
|
||||
|
||||
const deploymentMockData = [
|
||||
{
|
||||
id: 15,
|
||||
name: 'review/diplo',
|
||||
url: '/root/acets-review-apps/environments/15',
|
||||
stop_url: '/root/acets-review-apps/environments/15/stop',
|
||||
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
|
||||
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
|
||||
external_url: 'http://diplo.',
|
||||
external_url_formatted: 'diplo.',
|
||||
deployed_at: '2017-03-22T22:44:42.258Z',
|
||||
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
|
||||
},
|
||||
];
|
||||
const createComponent = () => {
|
||||
const Component = Vue.extend(deploymentComponent);
|
||||
const mr = {
|
||||
deployments: deploymentMockData,
|
||||
};
|
||||
const service = {};
|
||||
|
||||
return new Component({
|
||||
el: document.createElement('div'),
|
||||
propsData: { mr, service },
|
||||
});
|
||||
};
|
||||
|
||||
describe('MRWidgetDeployment', () => {
|
||||
describe('props', () => {
|
||||
it('should have props', () => {
|
||||
const { mr, service } = deploymentComponent.props;
|
||||
|
||||
expect(mr.type instanceof Object).toBeTruthy();
|
||||
expect(mr.required).toBeTruthy();
|
||||
|
||||
expect(service.type instanceof Object).toBeTruthy();
|
||||
expect(service.required).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
let vm = createComponent();
|
||||
const deployment = deploymentMockData[0];
|
||||
|
||||
describe('formatDate', () => {
|
||||
it('should work', () => {
|
||||
const readable = getTimeago().format(deployment.deployed_at);
|
||||
expect(vm.formatDate(deployment.deployed_at)).toEqual(readable);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasExternalUrls', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasExternalUrls(deployment)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false when there is not enough information', () => {
|
||||
expect(vm.hasExternalUrls()).toBeFalsy();
|
||||
expect(vm.hasExternalUrls({ external_url: 'Diplo' })).toBeFalsy();
|
||||
expect(vm.hasExternalUrls({ external_url_formatted: 'Diplo' })).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDeploymentTime', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasDeploymentTime(deployment)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false when there is not enough information', () => {
|
||||
expect(vm.hasDeploymentTime()).toBeFalsy();
|
||||
expect(vm.hasDeploymentTime({ deployed_at: 'Diplo' })).toBeFalsy();
|
||||
expect(vm.hasDeploymentTime({ deployed_at_formatted: 'Diplo' })).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDeploymentMeta', () => {
|
||||
it('should return true', () => {
|
||||
expect(vm.hasDeploymentMeta(deployment)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false when there is not enough information', () => {
|
||||
expect(vm.hasDeploymentMeta()).toBeFalsy();
|
||||
expect(vm.hasDeploymentMeta({ url: 'Diplo' })).toBeFalsy();
|
||||
expect(vm.hasDeploymentMeta({ name: 'Diplo' })).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('stopEnvironment', () => {
|
||||
const url = '/foo/bar';
|
||||
const returnPromise = () => new Promise((resolve) => {
|
||||
resolve({
|
||||
data: {
|
||||
redirect_url: url,
|
||||
},
|
||||
});
|
||||
});
|
||||
const mockStopEnvironment = () => {
|
||||
vm.stopEnvironment(deploymentMockData);
|
||||
return vm;
|
||||
};
|
||||
|
||||
it('should show a confirm dialog and call service.stopEnvironment when confirmed', (done) => {
|
||||
spyOn(window, 'confirm').and.returnValue(true);
|
||||
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(true));
|
||||
spyOn(urlUtils, 'visitUrl').and.returnValue(true);
|
||||
vm = mockStopEnvironment();
|
||||
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
expect(MRWidgetService.stopEnvironment).toHaveBeenCalledWith(deploymentMockData.stop_url);
|
||||
setTimeout(() => {
|
||||
expect(urlUtils.visitUrl).toHaveBeenCalledWith(url);
|
||||
done();
|
||||
}, 333);
|
||||
});
|
||||
|
||||
it('should show a confirm dialog but should not work if the dialog is rejected', () => {
|
||||
spyOn(window, 'confirm').and.returnValue(false);
|
||||
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(false));
|
||||
vm = mockStopEnvironment();
|
||||
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
expect(MRWidgetService.stopEnvironment).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
let vm;
|
||||
let el;
|
||||
const [deployment] = deploymentMockData;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = createComponent(deploymentMockData);
|
||||
el = vm.$el;
|
||||
});
|
||||
|
||||
it('should render template elements correctly', () => {
|
||||
expect(el.classList.contains('mr-widget-heading')).toBeTruthy();
|
||||
expect(el.querySelector('.js-icon-link')).toBeDefined();
|
||||
expect(el.querySelector('.js-deploy-meta').getAttribute('href')).toEqual(deployment.url);
|
||||
expect(el.querySelector('.js-deploy-meta').innerText).toContain(deployment.name);
|
||||
expect(el.querySelector('.js-deploy-url').getAttribute('href')).toEqual(deployment.external_url);
|
||||
expect(el.querySelector('.js-deploy-url').innerText).toContain(deployment.external_url_formatted);
|
||||
expect(el.querySelector('.js-deploy-time').innerText).toContain(vm.formatDate(deployment.deployed_at));
|
||||
expect(el.querySelector('.js-mr-memory-usage')).toBeDefined();
|
||||
expect(el.querySelector('button')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should list multiple deployments', (done) => {
|
||||
vm.mr.deployments.push(deployment);
|
||||
vm.mr.deployments.push(deployment);
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(el.querySelectorAll('.ci-widget').length).toEqual(3);
|
||||
expect(el.querySelectorAll('.js-mr-memory-usage').length).toEqual(3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have some elements when there is not enough data', (done) => {
|
||||
vm.mr.deployments = [{}];
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(el.querySelectorAll('.js-deploy-meta').length).toEqual(0);
|
||||
expect(el.querySelectorAll('.js-deploy-url').length).toEqual(0);
|
||||
expect(el.querySelectorAll('.js-deploy-time').length).toEqual(0);
|
||||
expect(el.querySelectorAll('.js-mr-memory-usage').length).toEqual(0);
|
||||
expect(el.querySelectorAll('.button').length).toEqual(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -123,17 +123,6 @@ describe('mrWidgetOptions', () => {
|
|||
expect(vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldRenderDeployments', () => {
|
||||
it('should return false for the initial data', () => {
|
||||
expect(vm.shouldRenderDeployments).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return true if there is deployments', () => {
|
||||
vm.mr.deployments.push({}, {});
|
||||
expect(vm.shouldRenderDeployments).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
|
@ -189,16 +178,16 @@ describe('mrWidgetOptions', () => {
|
|||
|
||||
describe('fetchDeployments', () => {
|
||||
it('should fetch deployments', (done) => {
|
||||
spyOn(vm.service, 'fetchDeployments').and.returnValue(returnPromise([{ deployment: 1 }]));
|
||||
spyOn(vm.service, 'fetchDeployments').and.returnValue(returnPromise([{ id: 1 }]));
|
||||
|
||||
vm.fetchDeployments();
|
||||
|
||||
setTimeout(() => {
|
||||
expect(vm.service.fetchDeployments).toHaveBeenCalled();
|
||||
expect(vm.mr.deployments.length).toEqual(1);
|
||||
expect(vm.mr.deployments[0].deployment).toEqual(1);
|
||||
expect(vm.mr.deployments[0].id).toBe(1);
|
||||
done();
|
||||
}, 333);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -368,34 +357,6 @@ describe('mrWidgetOptions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('components', () => {
|
||||
it('should register all components', () => {
|
||||
const comps = mrWidgetOptions.components;
|
||||
expect(comps['mr-widget-header']).toBeDefined();
|
||||
expect(comps['mr-widget-merge-help']).toBeDefined();
|
||||
expect(comps['mr-widget-pipeline']).toBeDefined();
|
||||
expect(comps['mr-widget-deployment']).toBeDefined();
|
||||
expect(comps['mr-widget-related-links']).toBeDefined();
|
||||
expect(comps['mr-widget-merged']).toBeDefined();
|
||||
expect(comps['mr-widget-closed']).toBeDefined();
|
||||
expect(comps['mr-widget-merging']).toBeDefined();
|
||||
expect(comps['mr-widget-failed-to-merge']).toBeDefined();
|
||||
expect(comps['mr-widget-wip']).toBeDefined();
|
||||
expect(comps['mr-widget-archived']).toBeDefined();
|
||||
expect(comps['mr-widget-conflicts']).toBeDefined();
|
||||
expect(comps['mr-widget-nothing-to-merge']).toBeDefined();
|
||||
expect(comps['mr-widget-not-allowed']).toBeDefined();
|
||||
expect(comps['mr-widget-missing-branch']).toBeDefined();
|
||||
expect(comps['mr-widget-ready-to-merge']).toBeDefined();
|
||||
expect(comps['mr-widget-checking']).toBeDefined();
|
||||
expect(comps['mr-widget-unresolved-discussions']).toBeDefined();
|
||||
expect(comps['mr-widget-pipeline-blocked']).toBeDefined();
|
||||
expect(comps['mr-widget-pipeline-failed']).toBeDefined();
|
||||
expect(comps['mr-widget-merge-when-pipeline-succeeds']).toBeDefined();
|
||||
expect(comps['mr-widget-maintainer-edit']).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering relatedLinks', () => {
|
||||
beforeEach((done) => {
|
||||
vm.mr.relatedLinks = {
|
||||
|
@ -454,4 +415,34 @@ describe('mrWidgetOptions', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('rendering deployments', () => {
|
||||
const deploymentMockData = {
|
||||
id: 15,
|
||||
name: 'review/diplo',
|
||||
url: '/root/acets-review-apps/environments/15',
|
||||
stop_url: '/root/acets-review-apps/environments/15/stop',
|
||||
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
|
||||
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
|
||||
external_url: 'http://diplo.',
|
||||
external_url_formatted: 'diplo.',
|
||||
deployed_at: '2017-03-22T22:44:42.258Z',
|
||||
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
|
||||
};
|
||||
|
||||
beforeEach((done) => {
|
||||
vm.mr.deployments.push({
|
||||
...deploymentMockData,
|
||||
}, {
|
||||
...deploymentMockData,
|
||||
id: deploymentMockData.id + 1,
|
||||
});
|
||||
|
||||
vm.$nextTick(done);
|
||||
});
|
||||
|
||||
it('renders multiple deployments', () => {
|
||||
expect(vm.$el.querySelectorAll('.deploy-heading').length).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue