Commit 2526d2dc authored by Alfredo Sumaran's avatar Alfredo Sumaran

Merge branch '20450-fix-ujs-actions' into 'master'

Use a button and a post request instead of UJS links - part 1 - Environments

See merge request !9688
parents 4b4e1f04 cbf1b656
/* eslint-disable no-param-reassign, no-new */ /* eslint-disable no-param-reassign, no-new */
/* global Flash */ /* global Flash */
import EnvironmentsService from '../services/environments_service';
import EnvironmentTable from './environments_table';
import EnvironmentsStore from '../stores/environments_store';
import eventHub from '../event_hub';
const Vue = window.Vue = require('vue'); const Vue = window.Vue = require('vue');
window.Vue.use(require('vue-resource')); window.Vue.use(require('vue-resource'));
const EnvironmentsService = require('../services/environments_service');
const EnvironmentTable = require('./environments_table');
const EnvironmentsStore = require('../stores/environments_store');
require('../../vue_shared/components/table_pagination'); require('../../vue_shared/components/table_pagination');
require('../../lib/utils/common_utils'); require('../../lib/utils/common_utils');
require('../../vue_shared/vue_resource_interceptor'); require('../../vue_shared/vue_resource_interceptor');
module.exports = Vue.component('environment-component', { export default Vue.component('environment-component', {
components: { components: {
'environment-table': EnvironmentTable, 'environment-table': EnvironmentTable,
...@@ -66,33 +67,15 @@ module.exports = Vue.component('environment-component', { ...@@ -66,33 +67,15 @@ module.exports = Vue.component('environment-component', {
* Toggles loading property. * Toggles loading property.
*/ */
created() { created() {
const scope = gl.utils.getParameterByName('scope') || this.visibility; this.service = new EnvironmentsService(this.endpoint);
const pageNumber = gl.utils.getParameterByName('page') || this.pageNumber;
const endpoint = `${this.endpoint}?scope=${scope}&page=${pageNumber}`;
const service = new EnvironmentsService(endpoint); this.fetchEnvironments();
this.isLoading = true; eventHub.$on('refreshEnvironments', this.fetchEnvironments);
},
return service.get() beforeDestroyed() {
.then(resp => ({ eventHub.$off('refreshEnvironments');
headers: resp.headers,
body: resp.json(),
}))
.then((response) => {
this.store.storeAvailableCount(response.body.available_count);
this.store.storeStoppedCount(response.body.stopped_count);
this.store.storeEnvironments(response.body.environments);
this.store.setPagination(response.headers);
})
.then(() => {
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the environments.', 'alert');
});
}, },
methods: { methods: {
...@@ -112,6 +95,32 @@ module.exports = Vue.component('environment-component', { ...@@ -112,6 +95,32 @@ module.exports = Vue.component('environment-component', {
gl.utils.visitUrl(param); gl.utils.visitUrl(param);
return param; return param;
}, },
fetchEnvironments() {
const scope = gl.utils.getParameterByName('scope') || this.visibility;
const pageNumber = gl.utils.getParameterByName('page') || this.pageNumber;
this.isLoading = true;
return this.service.get(scope, pageNumber)
.then(resp => ({
headers: resp.headers,
body: resp.json(),
}))
.then((response) => {
this.store.storeAvailableCount(response.body.available_count);
this.store.storeStoppedCount(response.body.stopped_count);
this.store.storeEnvironments(response.body.environments);
this.store.setPagination(response.headers);
})
.then(() => {
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the environments.');
});
},
}, },
template: ` template: `
...@@ -144,7 +153,7 @@ module.exports = Vue.component('environment-component', { ...@@ -144,7 +153,7 @@ module.exports = Vue.component('environment-component', {
<div class="content-list environments-container"> <div class="content-list environments-container">
<div class="environments-list-loading text-center" v-if="isLoading"> <div class="environments-list-loading text-center" v-if="isLoading">
<i class="fa fa-spinner fa-spin"></i> <i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</div> </div>
<div class="blank-state blank-state-no-icon" <div class="blank-state blank-state-no-icon"
...@@ -173,7 +182,8 @@ module.exports = Vue.component('environment-component', { ...@@ -173,7 +182,8 @@ module.exports = Vue.component('environment-component', {
<environment-table <environment-table
:environments="state.environments" :environments="state.environments"
:can-create-deployment="canCreateDeploymentParsed" :can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"/> :can-read-environment="canReadEnvironmentParsed"
:service="service"/>
</div> </div>
<table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1" <table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1"
......
const Vue = require('vue'); /* global Flash */
const playIconSvg = require('icons/_icon_play.svg'); /* eslint-disable no-new */
module.exports = Vue.component('actions-component', { import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
export default {
props: { props: {
actions: { actions: {
type: Array, type: Array,
required: false, required: false,
default: () => [], default: () => [],
}, },
service: {
type: Object,
required: true,
},
}, },
data() { data() {
return { playIconSvg }; return {
playIconSvg,
isLoading: false,
};
},
methods: {
onClickAction(endpoint) {
this.isLoading = true;
this.service.postAction(endpoint)
.then(() => {
this.isLoading = false;
eventHub.$emit('refreshEnvironments');
})
.catch(() => {
this.isLoading = false;
new Flash('An error occured while making the request.');
});
},
}, },
template: ` template: `
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<button class="dropdown btn btn-default dropdown-new" data-toggle="dropdown"> <button
class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container"
data-toggle="dropdown"
:disabled="isLoading">
<span> <span>
<span class="js-dropdown-play-icon-container" v-html="playIconSvg"></span> <span v-html="playIconSvg"></span>
<i class="fa fa-caret-down"></i> <i class="fa fa-caret-down" aria-hidden="true"></i>
<i v-if="isLoading" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</span> </span>
<ul class="dropdown-menu dropdown-menu-align-right"> <ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions"> <li v-for="action in actions">
<a :href="action.play_path" <button
data-method="post" @click="onClickAction(action.play_path)"
rel="nofollow" class="js-manual-action-link no-btn">
class="js-manual-action-link">
${playIconSvg} ${playIconSvg}
<span> <span>
{{action.name}} {{action.name}}
</span> </span>
</a> </button>
</li> </li>
</ul> </ul>
</button> </button>
</div> </div>
`, `,
}); };
/** /**
* Renders the external url link in environments table. * Renders the external url link in environments table.
*/ */
const Vue = require('vue'); export default {
module.exports = Vue.component('external-url-component', {
props: { props: {
externalUrl: { externalUrl: {
type: String, type: String,
...@@ -12,8 +10,12 @@ module.exports = Vue.component('external-url-component', { ...@@ -12,8 +10,12 @@ module.exports = Vue.component('external-url-component', {
}, },
template: ` template: `
<a class="btn external_url" :href="externalUrl" target="_blank"> <a
<i class="fa fa-external-link"></i> class="btn external_url"
:href="externalUrl"
target="_blank"
title="Environment external URL">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a> </a>
`, `,
}); };
const Vue = require('vue'); import Timeago from 'timeago.js';
const Timeago = require('timeago.js'); import ActionsComponent from './environment_actions';
import ExternalUrlComponent from './environment_external_url';
require('../../lib/utils/text_utility'); import StopComponent from './environment_stop';
require('../../vue_shared/components/commit'); import RollbackComponent from './environment_rollback';
const ActionsComponent = require('./environment_actions'); import TerminalButtonComponent from './environment_terminal_button';
const ExternalUrlComponent = require('./environment_external_url'); import '../../lib/utils/text_utility';
const StopComponent = require('./environment_stop'); import '../../vue_shared/components/commit';
const RollbackComponent = require('./environment_rollback');
const TerminalButtonComponent = require('./environment_terminal_button');
/** /**
* Envrionment Item Component * Envrionment Item Component
...@@ -17,7 +15,7 @@ const TerminalButtonComponent = require('./environment_terminal_button'); ...@@ -17,7 +15,7 @@ const TerminalButtonComponent = require('./environment_terminal_button');
const timeagoInstance = new Timeago(); const timeagoInstance = new Timeago();
module.exports = Vue.component('environment-item', { export default {
components: { components: {
'commit-component': gl.CommitComponent, 'commit-component': gl.CommitComponent,
...@@ -46,6 +44,11 @@ module.exports = Vue.component('environment-item', { ...@@ -46,6 +44,11 @@ module.exports = Vue.component('environment-item', {
required: false, required: false,
default: false, default: false,
}, },
service: {
type: Object,
required: true,
},
}, },
computed: { computed: {
...@@ -489,22 +492,25 @@ module.exports = Vue.component('environment-item', { ...@@ -489,22 +492,25 @@ module.exports = Vue.component('environment-item', {
<td class="environments-actions"> <td class="environments-actions">
<div v-if="!model.isFolder" class="btn-group pull-right" role="group"> <div v-if="!model.isFolder" class="btn-group pull-right" role="group">
<actions-component v-if="hasManualActions && canCreateDeployment" <actions-component v-if="hasManualActions && canCreateDeployment"
:service="service"
:actions="manualActions"/> :actions="manualActions"/>
<external-url-component v-if="externalURL && canReadEnvironment" <external-url-component v-if="externalURL && canReadEnvironment"
:external-url="externalURL"/> :external-url="externalURL"/>
<stop-component v-if="hasStopAction && canCreateDeployment" <stop-component v-if="hasStopAction && canCreateDeployment"
:stop-url="model.stop_path"/> :stop-url="model.stop_path"
:service="service"/>
<terminal-button-component v-if="model && model.terminal_path" <terminal-button-component v-if="model && model.terminal_path"
:terminal-path="model.terminal_path"/> :terminal-path="model.terminal_path"/>
<rollback-component v-if="canRetry && canCreateDeployment" <rollback-component v-if="canRetry && canCreateDeployment"
:is-last-deployment="isLastDeployment" :is-last-deployment="isLastDeployment"
:retry-url="retryUrl"/> :retry-url="retryUrl"
:service="service"/>
</div> </div>
</td> </td>
</tr> </tr>
`, `,
}); };
/* global Flash */
/* eslint-disable no-new */
/** /**
* Renders Rollback or Re deploy button in environments table depending * Renders Rollback or Re deploy button in environments table depending
* of the provided property `isLastDeployment` * of the provided property `isLastDeployment`.
*
* Makes a post request when the button is clicked.
*/ */
const Vue = require('vue'); import eventHub from '../event_hub';
module.exports = Vue.component('rollback-component', { export default {
props: { props: {
retryUrl: { retryUrl: {
type: String, type: String,
...@@ -15,16 +19,49 @@ module.exports = Vue.component('rollback-component', { ...@@ -15,16 +19,49 @@ module.exports = Vue.component('rollback-component', {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
service: {
type: Object,
required: true,
},
},
data() {
return {
isLoading: false,
};
},
methods: {
onClick() {
this.isLoading = true;
this.service.postAction(this.retryUrl)
.then(() => {
this.isLoading = false;
eventHub.$emit('refreshEnvironments');
})
.catch(() => {
this.isLoading = false;
new Flash('An error occured while making the request.');
});
},
}, },
template: ` template: `
<a class="btn" :href="retryUrl" data-method="post" rel="nofollow"> <button type="button"
class="btn"
@click="onClick"
:disabled="isLoading">
<span v-if="isLastDeployment"> <span v-if="isLastDeployment">
Re-deploy Re-deploy
</span> </span>
<span v-else> <span v-else>
Rollback Rollback
</span> </span>
</a>
<i v-if="isLoading" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</button>
`, `,
}); };
/* global Flash */
/* eslint-disable no-new, no-alert */
/** /**
* Renders the stop "button" that allows stop an environment. * Renders the stop "button" that allows stop an environment.
* Used in environments table. * Used in environments table.
*/ */
const Vue = require('vue'); import eventHub from '../event_hub';
module.exports = Vue.component('stop-component', { export default {
props: { props: {
stopUrl: { stopUrl: {
type: String, type: String,
default: '', default: '',
}, },
service: {
type: Object,
required: true,
},
},
data() {
return {
isLoading: false,
};
},
methods: {
onClick() {
if (confirm('Are you sure you want to stop this environment?')) {
this.isLoading = true;
this.service.postAction(this.retryUrl)
.then(() => {
this.isLoading = false;
eventHub.$emit('refreshEnvironments');
})
.catch(() => {
this.isLoading = false;
new Flash('An error occured while making the request.', 'alert');
});
}
},
}, },
template: ` template: `
<a class="btn stop-env-link" <button type="button"
:href="stopUrl" class="btn stop-env-link"
data-confirm="Are you sure you want to stop this environment?" @click="onClick"
data-method="post" :disabled="isLoading"
rel="nofollow"> title="Stop Environment">
<i class="fa fa-stop stop-env-icon" aria-hidden="true"></i> <i class="fa fa-stop stop-env-icon" aria-hidden="true"></i>
</a> <i v-if="isLoading" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</button>
`, `,
}); };
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
* Renders a terminal button to open a web terminal. * Renders a terminal button to open a web terminal.
* Used in environments table. * Used in environments table.
*/ */
const Vue = require('vue'); import terminalIconSvg from 'icons/_icon_terminal.svg';
const terminalIconSvg = require('icons/_icon_terminal.svg');
module.exports = Vue.component('terminal-button-component', { export default {
props: { props: {
terminalPath: { terminalPath: {
type: String, type: String,
required: false,
default: '', default: '',
}, },
}, },
...@@ -19,8 +19,9 @@ module.exports = Vue.component('terminal-button-component', { ...@@ -19,8 +19,9 @@ module.exports = Vue.component('terminal-button-component', {
template: ` template: `
<a class="btn terminal-button" <a class="btn terminal-button"
title="Open web terminal"
:href="terminalPath"> :href="terminalPath">
${terminalIconSvg} ${terminalIconSvg}
</a> </a>
`, `,
}); };
/** /**
* Render environments table. * Render environments table.
*/ */
const Vue = require('vue'); import EnvironmentItem from './environment_item';
const EnvironmentItem = require('./environment_item');
module.exports = Vue.component('environment-table-component', {
export default {
components: { components: {
'environment-item': EnvironmentItem, 'environment-item': EnvironmentItem,
}, },
...@@ -28,6 +26,11 @@ module.exports = Vue.component('environment-table-component', { ...@@ -28,6 +26,11 @@ module.exports = Vue.component('environment-table-component', {
required: false, required: false,
default: false, default: false,
}, },
service: {
type: Object,
required: true,
},
}, },
template: ` template: `
...@@ -48,9 +51,10 @@ module.exports = Vue.component('environment-table-component', { ...@@ -48,9 +51,10 @@ module.exports = Vue.component('environment-table-component', {
<tr is="environment-item" <tr is="environment-item"
:model="model" :model="model"
:can-create-deployment="canCreateDeployment" :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"></tr> :can-read-environment="canReadEnvironment"
:service="service"></tr>
</template> </template>
</tbody> </tbody>
</table> </table>
`, `,
}); };
const EnvironmentsComponent = require('./components/environment'); import EnvironmentsComponent from './components/environment';
$(() => { $(() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
......
import Vue from 'vue';
export default new Vue();
const EnvironmentsFolderComponent = require('./environments_folder_view'); import EnvironmentsFolderComponent from './environments_folder_view';
$(() => { $(() => {
window.gl = window.gl || {}; window.gl = window.gl || {};
......
/* eslint-disable no-param-reassign, no-new */ /* eslint-disable no-param-reassign, no-new */
/* global Flash */ /* global Flash */
import EnvironmentsService from '../services/environments_service';
import EnvironmentTable from '../components/environments_table';
import EnvironmentsStore from '../stores/environments_store';
const Vue = window.Vue = require('vue'); const Vue = window.Vue = require('vue');
window.Vue.use(require('vue-resource')); window.Vue.use(require('vue-resource'));
const EnvironmentsService = require('../services/environments_service');
const EnvironmentTable = require('../components/environments_table');
const EnvironmentsStore = require('../stores/environments_store');
require('../../vue_shared/components/table_pagination'); require('../../vue_shared/components/table_pagination');
require('../../lib/utils/common_utils'); require('../../lib/utils/common_utils');
require('../../vue_shared/vue_resource_interceptor'); require('../../vue_shared/vue_resource_interceptor');
module.exports = Vue.component('environment-folder-view', { export default Vue.component('environment-folder-view', {
components: { components: {
'environment-table': EnvironmentTable, 'environment-table': EnvironmentTable,
...@@ -88,11 +88,11 @@ module.exports = Vue.component('environment-folder-view', { ...@@ -88,11 +88,11 @@ module.exports = Vue.component('environment-folder-view', {
const endpoint = `${this.endpoint}?scope=${scope}&page=${pageNumber}`; const endpoint = `${this.endpoint}?scope=${scope}&page=${pageNumber}`;
const service = new EnvironmentsService(endpoint); this.service = new EnvironmentsService(endpoint);
this.isLoading = true; this.isLoading = true;
return service.get() return this.service.get()
.then(resp => ({ .then(resp => ({
headers: resp.headers, headers: resp.headers,
body: resp.json(), body: resp.json(),
...@@ -168,13 +168,12 @@ module.exports = Vue.component('environment-folder-view', { ...@@ -168,13 +168,12 @@ module.exports = Vue.component('environment-folder-view', {
:can-read-environment="canReadEnvironmentParsed" :can-read-environment="canReadEnvironmentParsed"
:play-icon-svg="playIconSvg" :play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg" :terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg"> :commit-icon-svg="commitIconSvg"
</environment-table> :service="service"/>
<table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1" <table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1"
:change="changePage" :change="changePage"
:pageInfo="state.paginationInformation"> :pageInfo="state.paginationInformation"/>
</table-pagination>
</div> </div>
</div> </div>
</div> </div>
......
const Vue = require('vue'); /* eslint-disable class-methods-use-this */
import Vue from 'vue';
class EnvironmentsService { export default class EnvironmentsService {
constructor(endpoint) { constructor(endpoint) {
this.environments = Vue.resource(endpoint); this.environments = Vue.resource(endpoint);
} }
get() { get(scope, page) {
return this.environments.get(); return this.environments.get({ scope, page });
} }
}
module.exports = EnvironmentsService; postAction(endpoint) {
return Vue.http.post(endpoint, {}, { emulateJSON: true });
}
}
require('~/lib/utils/common_utils'); import '~/lib/utils/common_utils';
/** /**
* Environments Store. * Environments Store.
* *
* Stores received environments, count of stopped environments and count of * Stores received environments, count of stopped environments and count of
* available environments. * available environments.
*/ */
class EnvironmentsStore { export default class EnvironmentsStore {
constructor() { constructor() {
this.state = {}; this.state = {};
this.state.environments = []; this.state.environments = [];
...@@ -86,5 +87,3 @@ class EnvironmentsStore { ...@@ -86,5 +87,3 @@ class EnvironmentsStore {
return count; return count;
} }
} }
module.exports = EnvironmentsStore;
...@@ -6,10 +6,6 @@ Vue.http.interceptors.push((request, next) => { ...@@ -6,10 +6,6 @@ Vue.http.interceptors.push((request, next) => {
Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1; Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1;
next((response) => { next((response) => {
if (typeof response.data === 'string') {
response.data = JSON.parse(response.data);
}
Vue.activeResources--; Vue.activeResources--;
}); });
}); });
......
...@@ -141,6 +141,14 @@ ...@@ -141,6 +141,14 @@
margin-right: 0; margin-right: 0;
} }
} }
.no-btn {
border: none;
background: none;
outline: none;
width: 100%;
text-align: left;
}
} }
} }
......
...@@ -111,10 +111,8 @@ feature 'Environments page', :feature, :js do ...@@ -111,10 +111,8 @@ feature 'Environments page', :feature, :js do
find('.js-dropdown-play-icon-container').click find('.js-dropdown-play-icon-container').click
expect(page).to have_content(action.name.humanize) expect(page).to have_content(action.name.humanize)
expect { click_link(action.name.humanize) } expect { find('.js-manual-action-link').click }
.not_to change { Ci::Pipeline.count } .not_to change { Ci::Pipeline.count }
expect(action.reload).to be_pending
end end
scenario 'does show build name and id' do scenario 'does show build name and id' do
...@@ -158,12 +156,6 @@ feature 'Environments page', :feature, :js do ...@@ -158,12 +156,6 @@ feature 'Environments page', :feature, :js do
expect(page).to have_selector('.stop-env-link') expect(page).to have_selector('.stop-env-link')
end end
scenario 'starts build when stop button clicked' do
find('.stop-env-link').click
expect(page).to have_content('close_app')
end
context 'for reporter' do context 'for reporter' do
let(:role) { :reporter } let(:role) { :reporter }
......
const ActionsComponent = require('~/environments/components/environment_actions'); import Vue from 'vue';
import actionsComp from '~/environments/components/environment_actions';
describe('Actions Component', () => { describe('Actions Component', () => {
preloadFixtures('static/environments/element.html.raw'); let ActionsComponent;
let actionsMock;
let spy;
let component;
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/element.html.raw'); ActionsComponent = Vue.extend(actionsComp);
});
it('should render a dropdown with the provided actions', () => { actionsMock = [
const actionsMock = [
{ {
name: 'bar', name: 'bar',
play_path: 'https://gitlab.com/play', play_path: 'https://gitlab.com/play',
...@@ -19,18 +21,27 @@ describe('Actions Component', () => { ...@@ -19,18 +21,27 @@ describe('Actions Component', () => {
}, },
]; ];
const component = new ActionsComponent({ spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
el: document.querySelector('.test-dom-element'), component = new ActionsComponent({
propsData: { propsData: {
actions: actionsMock, actions: actionsMock,
service: {
postAction: spy,
}, },
},
}).$mount();
}); });
it('should render a dropdown with the provided actions', () => {
expect( expect(
component.$el.querySelectorAll('.dropdown-menu li').length, component.$el.querySelectorAll('.dropdown-menu li').length,
).toEqual(actionsMock.length); ).toEqual(actionsMock.length);
expect( });
component.$el.querySelector('.dropdown-menu li a').getAttribute('href'),
).toEqual(actionsMock[0].play_path); it('should call the service when an action is clicked', () => {
component.$el.querySelector('.dropdown').click();
component.$el.querySelector('.js-manual-action-link').click();
expect(spy).toHaveBeenCalledWith(actionsMock[0].play_path);
}); });
}); });
const ExternalUrlComponent = require('~/environments/components/environment_external_url'); import Vue from 'vue';
import externalUrlComp from '~/environments/components/environment_external_url';
describe('External URL Component', () => { describe('External URL Component', () => {
preloadFixtures('static/environments/element.html.raw'); let ExternalUrlComponent;
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/element.html.raw'); ExternalUrlComponent = Vue.extend(externalUrlComp);
}); });
it('should link to the provided externalUrl prop', () => { it('should link to the provided externalUrl prop', () => {
const externalURL = 'https://gitlab.com'; const externalURL = 'https://gitlab.com';
const component = new ExternalUrlComponent({ const component = new ExternalUrlComponent({
el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
externalUrl: externalURL, externalUrl: externalURL,
}, },
}); }).$mount();
expect(component.$el.getAttribute('href')).toEqual(externalURL); expect(component.$el.getAttribute('href')).toEqual(externalURL);
expect(component.$el.querySelector('fa-external-link')).toBeDefined(); expect(component.$el.querySelector('fa-external-link')).toBeDefined();
......
window.timeago = require('timeago.js'); import 'timeago.js';
const EnvironmentItem = require('~/environments/components/environment_item'); import Vue from 'vue';
import environmentItemComp from '~/environments/components/environment_item';
describe('Environment item', () => { describe('Environment item', () => {
preloadFixtures('static/environments/table.html.raw'); let EnvironmentItem;
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/table.html.raw'); EnvironmentItem = Vue.extend(environmentItemComp);
}); });
describe('When item is folder', () => { describe('When item is folder', () => {
...@@ -21,13 +23,13 @@ describe('Environment item', () => { ...@@ -21,13 +23,13 @@ describe('Environment item', () => {
}; };
component = new EnvironmentItem({ component = new EnvironmentItem({
el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: mockItem, model: mockItem,
canCreateDeployment: false, canCreateDeployment: false,
canReadEnvironment: true, canReadEnvironment: true,
service: {},
}, },
}); }).$mount();
}); });
it('Should render folder icon and name', () => { it('Should render folder icon and name', () => {
...@@ -109,13 +111,13 @@ describe('Environment item', () => { ...@@ -109,13 +111,13 @@ describe('Environment item', () => {
}; };
component = new EnvironmentItem({ component = new EnvironmentItem({
el: document.querySelector('tr#environment-row'),
propsData: { propsData: {
model: environment, model: environment,
canCreateDeployment: true, canCreateDeployment: true,
canReadEnvironment: true, canReadEnvironment: true,
service: {},
}, },
}); }).$mount();
}); });
it('should render environment name', () => { it('should render environment name', () => {
......
const RollbackComponent = require('~/environments/components/environment_rollback'); import Vue from 'vue';
import rollbackComp from '~/environments/components/environment_rollback';
describe('Rollback Component', () => { describe('Rollback Component', () => {
preloadFixtures('static/environments/element.html.raw');
const retryURL = 'https://gitlab.com/retry'; const retryURL = 'https://gitlab.com/retry';
let RollbackComponent;
let spy;
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/element.html.raw'); RollbackComponent = Vue.extend(rollbackComp);
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
}); });
it('Should link to the provided retryUrl', () => { it('Should render Re-deploy label when isLastDeployment is true', () => {
const component = new RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
isLastDeployment: true, isLastDeployment: true,
service: {
postAction: spy,
}, },
}); },
}).$mount();
expect(component.$el.getAttribute('href')).toEqual(retryURL); expect(component.$el.querySelector('span').textContent).toContain('Re-deploy');
}); });
it('Should render Re-deploy label when isLastDeployment is true', () => { it('Should render Rollback label when isLastDeployment is false', () => {
const component = new RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
isLastDeployment: true, isLastDeployment: false,
service: {
postAction: spy,
}, },
}); },
}).$mount();
expect(component.$el.querySelector('span').textContent).toContain('Re-deploy'); expect(component.$el.querySelector('span').textContent).toContain('Rollback');
}); });
it('Should render Rollback label when isLastDeployment is false', () => { it('should call the service when the button is clicked', () => {
const component = new RollbackComponent({ const component = new RollbackComponent({
el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
retryUrl: retryURL, retryUrl: retryURL,
isLastDeployment: false, isLastDeployment: false,
service: {
postAction: spy,
}, },
}); },
}).$mount();
expect(component.$el.querySelector('span').textContent).toContain('Rollback'); component.$el.click();
expect(spy).toHaveBeenCalledWith(retryURL);
}); });
}); });
const Vue = require('vue'); import Vue from 'vue';
require('~/flash'); import '~/flash';
const EnvironmentsComponent = require('~/environments/components/environment'); import EnvironmentsComponent from '~/environments/components/environment';
const { environment } = require('./mock_data'); import { environment } from './mock_data';
describe('Environment', () => { describe('Environment', () => {
preloadFixtures('static/environments/environments.html.raw'); preloadFixtures('static/environments/environments.html.raw');
......
const StopComponent = require('~/environments/components/environment_stop'); import Vue from 'vue';
import stopComp from '~/environments/components/environment_stop';
describe('Stop Component', () => { describe('Stop Component', () => {
preloadFixtures('static/environments/element.html.raw'); let StopComponent;
let stopURL;
let component; let component;
let spy;
const stopURL = '/stop';
beforeEach(() => { beforeEach(() => {
loadFixtures('static/environments/element.html.raw'); StopComponent = Vue.extend(stopComp);
spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve());
spyOn(window, 'confirm').and.returnValue(true);
stopURL = '/stop';
component = new StopComponent({ component = new StopComponent({
el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
stopUrl: stopURL, stopUrl: stopURL,
service: {
postAction: spy,
}, },
}); },
}).$mount();
}); });
it('should link to the provided URL', () => { it('should render a button to stop the environment', () => {
expect(component.$el.getAttribute('href')).toEqual(stopURL); expect(component.$el.tagName).toEqual('BUTTON');
expect(component.$el.getAttribute('title')).toEqual('Stop Environment');
}); });
it('should have a data-confirm attribute', () => { it('should call the service when an action is clicked', () => {
expect(component.$el.getAttribute('data-confirm')).toEqual('Are you sure you want to stop this environment?'); component.$el.click();
expect(spy).toHaveBeenCalled();
}); });
}); });
const EnvironmentTable = require('~/environments/components/environments_table'); import Vue from 'vue';
import environmentTableComp from '~/environments/components/environments_table';
describe('Environment item', () => { describe('Environment item', () => {
preloadFixtures('static/environments/element.html.raw'); preloadFixtures('static/environments/element.html.raw');
...@@ -16,14 +17,17 @@ describe('Environment item', () => { ...@@ -16,14 +17,17 @@ describe('Environment item', () => {
}, },
}; };
const EnvironmentTable = Vue.extend(environmentTableComp);
const component = new EnvironmentTable({ const component = new EnvironmentTable({
el: document.querySelector('.test-dom-element'), el: document.querySelector('.test-dom-element'),
propsData: { propsData: {
environments: [{ mockItem }], environments: [{ mockItem }],
canCreateDeployment: false, canCreateDeployment: false,
canReadEnvironment: true, canReadEnvironment: true,
service: {},
}, },
}); }).$mount();
expect(component.$el.tagName).toEqual('TABLE'); expect(component.$el.tagName).toEqual('TABLE');
}); });
......
import Vue from 'vue';
import terminalComp from '~/environments/components/environment_terminal_button';
describe('Stop Component', () => {
let TerminalComponent;
let component;
const terminalPath = '/path';
beforeEach(() => {
TerminalComponent = Vue.extend(terminalComp);
component = new TerminalComponent({
propsData: {
terminalPath,
},
}).$mount();
});
it('should render a link to open a web terminal with the provided path', () => {
expect(component.$el.tagName).toEqual('A');
expect(component.$el.getAttribute('title')).toEqual('Open web terminal');
expect(component.$el.getAttribute('href')).toEqual(terminalPath);
});
});
const Store = require('~/environments/stores/environments_store'); import Store from '~/environments/stores/environments_store';
const { environmentsList, serverData } = require('./mock_data'); import { environmentsList, serverData } from './mock_data';
(() => { (() => {
describe('Store', () => { describe('Store', () => {
......
const Vue = require('vue'); import Vue from 'vue';
require('~/flash'); import '~/flash';
const EnvironmentsFolderViewComponent = require('~/environments/folder/environments_folder_view'); import EnvironmentsFolderViewComponent from '~/environments/folder/environments_folder_view';
const { environmentsList } = require('../mock_data'); import { environmentsList } from '../mock_data';
describe('Environments Folder View', () => { describe('Environments Folder View', () => {
preloadFixtures('static/environments/environments_folder_view.html.raw'); preloadFixtures('static/environments/environments_folder_view.html.raw');
......
const environmentsList = [ export const environmentsList = [
{ {
name: 'DEV', name: 'DEV',
size: 1, size: 1,
...@@ -30,7 +30,7 @@ const environmentsList = [ ...@@ -30,7 +30,7 @@ const environmentsList = [
}, },
]; ];
const serverData = [ export const serverData = [
{ {
name: 'DEV', name: 'DEV',
size: 1, size: 1,
...@@ -67,7 +67,7 @@ const serverData = [ ...@@ -67,7 +67,7 @@ const serverData = [
}, },
]; ];
const environment = { export const environment = {
name: 'DEV', name: 'DEV',
size: 1, size: 1,
latest: { latest: {
...@@ -84,9 +84,3 @@ const environment = { ...@@ -84,9 +84,3 @@ const environment = {
updated_at: '2017-01-31T10:53:46.894Z', updated_at: '2017-01-31T10:53:46.894Z',
}, },
}; };
module.exports = {
environmentsList,
environment,
serverData,
};
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