Move change page param to utility function
Add tests Adds folder name in the top of the table
This commit is contained in:
parent
73accafe43
commit
1285d62906
|
@ -50,15 +50,15 @@ module.exports = Vue.component('environment-component', {
|
|||
},
|
||||
|
||||
canReadEnvironmentParsed() {
|
||||
return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
|
||||
return gl.utils.convertPermissionToBoolean(this.canReadEnvironment);
|
||||
},
|
||||
|
||||
canCreateDeploymentParsed() {
|
||||
return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
|
||||
return gl.utils.convertPermissionToBoolean(this.canCreateDeployment);
|
||||
},
|
||||
|
||||
canCreateEnvironmentParsed() {
|
||||
return this.$options.convertPermissionToBoolean(this.canCreateEnvironment);
|
||||
return gl.utils.convertPermissionToBoolean(this.canCreateEnvironment);
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -97,15 +97,6 @@ module.exports = Vue.component('environment-component', {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts permission provided as strings to booleans.
|
||||
* @param {String} string
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
convertPermissionToBoolean(string) {
|
||||
return string === 'true';
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleRow(model) {
|
||||
return this.store.toggleFolder(model.name);
|
||||
|
@ -114,26 +105,11 @@ module.exports = Vue.component('environment-component', {
|
|||
/**
|
||||
* Will change the page number and update the URL.
|
||||
*
|
||||
* If no search params are present, we'll add param for page
|
||||
* If param for page is already present, we'll update it
|
||||
* If there are params but none for page, we'll add it at the end.
|
||||
*
|
||||
* @param {Number} pageNumber desired page to go to.
|
||||
* @return {String}
|
||||
*/
|
||||
changePage(pageNumber) {
|
||||
let param;
|
||||
if (window.location.search.length === 0) {
|
||||
param = `?page=${pageNumber}`;
|
||||
}
|
||||
|
||||
if (window.location.search.indexOf('page') !== -1) {
|
||||
param = window.location.search.replace(/page=\d/g, `page=${pageNumber}`);
|
||||
}
|
||||
|
||||
if (window.location.search.length &&
|
||||
window.location.search.indexOf('page') === -1) {
|
||||
param = `${window.location.search}&page=${pageNumber}`;
|
||||
}
|
||||
const param = gl.utils.setParamInURL('page', pageNumber);
|
||||
|
||||
gl.utils.visitUrl(param);
|
||||
return param;
|
||||
|
|
|
@ -99,7 +99,7 @@ module.exports = Vue.component('environment-item', {
|
|||
* @returns {Boolean}
|
||||
*/
|
||||
hasStopAction() {
|
||||
return this.model.latest['stop_action?'];
|
||||
return this.model.latest && this.model.latest['stop_action?'];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -414,7 +414,7 @@ module.exports = Vue.component('environment-item', {
|
|||
* @return {String}
|
||||
*/
|
||||
folderUrl() {
|
||||
return `${window.location.pathname}/folders/${this.model.latest.id}`;
|
||||
return `${window.location.pathname}/folders/${this.model.name}`;
|
||||
},
|
||||
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const EnvironmentsFolderComponent = require('./environments_folder_view');
|
||||
require('../../vue_shared/vue_resource_interceptor');
|
||||
|
||||
$(() => {
|
||||
window.gl = window.gl || {};
|
||||
|
|
|
@ -6,6 +6,7 @@ Vue.use(require('vue-resource'));
|
|||
const EnvironmentsService = require('../services/environments_service');
|
||||
const EnvironmentTable = require('../components/environments_table');
|
||||
const Store = require('../stores/environments_store');
|
||||
require('../../vue_shared/components/table_pagination');
|
||||
require('../../lib/utils/common_utils');
|
||||
|
||||
module.exports = Vue.component('environment-folder-view', {
|
||||
|
@ -19,9 +20,11 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
const environmentsData = document.querySelector('#environments-folder-list-view').dataset;
|
||||
const store = new Store();
|
||||
const endpoint = `${window.location.pathname}.json`;
|
||||
const folderName = window.location.pathname.substr(window.location.pathname.lastIndexOf('/') + 1);
|
||||
|
||||
return {
|
||||
store,
|
||||
folderName,
|
||||
endpoint,
|
||||
state: store.state,
|
||||
visibility: 'available',
|
||||
|
@ -47,21 +50,30 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
},
|
||||
|
||||
canReadEnvironmentParsed() {
|
||||
return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
|
||||
return gl.utils.convertPermissionToBoolean(this.canReadEnvironment);
|
||||
},
|
||||
|
||||
canCreateDeploymentParsed() {
|
||||
return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
|
||||
return gl.utils.convertPermissionToBoolean(this.canCreateDeployment);
|
||||
},
|
||||
|
||||
/**
|
||||
* URL to link in the stopped tab.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
stoppedPath() {
|
||||
return `${window.location.pathname}?scope=stopped`;
|
||||
},
|
||||
|
||||
/**
|
||||
* URL to link in the available tab.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
availablePath() {
|
||||
return window.location.pathname;
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -84,6 +96,8 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
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.storePagination(response.headers);
|
||||
})
|
||||
|
@ -96,45 +110,14 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Transforms the url parameter into an object and
|
||||
* returns the one requested.
|
||||
*
|
||||
* @param {String} param
|
||||
* @returns {String} The value of the requested parameter.
|
||||
*/
|
||||
getQueryParameter(parameter) {
|
||||
return window.location.search.substring(1).split('&').reduce((acc, param) => {
|
||||
const paramSplited = param.split('=');
|
||||
acc[paramSplited[0]] = paramSplited[1];
|
||||
return acc;
|
||||
}, {})[parameter];
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Will change the page number and update the URL.
|
||||
*
|
||||
* If no search params are present, we'll add param for page
|
||||
* If param for page is already present, we'll update it
|
||||
* If there are params but none for page, we'll add it at the end.
|
||||
*
|
||||
* @param {Number} pageNumber desired page to go to.
|
||||
*/
|
||||
changePage(pageNumber) {
|
||||
let param;
|
||||
if (window.location.search.length === 0) {
|
||||
param = `?page=${pageNumber}`;
|
||||
}
|
||||
|
||||
if (window.location.search.indexOf('page') !== -1) {
|
||||
param = window.location.search.replace(/page=\d/g, `page=${pageNumber}`);
|
||||
}
|
||||
|
||||
if (window.location.search.length &&
|
||||
window.location.search.indexOf('page') === -1) {
|
||||
param = `${window.location.search}&page=${pageNumber}`;
|
||||
}
|
||||
const param = gl.utils.setParamInURL('page', pageNumber);
|
||||
|
||||
gl.utils.visitUrl(param);
|
||||
return param;
|
||||
|
@ -143,13 +126,15 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
|
||||
template: `
|
||||
<div :class="cssContainerClass">
|
||||
<div class="top-area">
|
||||
<div class="top-area" v-if="!isLoading">
|
||||
|
||||
<h3>FOLDER NAME</h3>
|
||||
<h4 class="js-folder-name environments-folder-name">
|
||||
Environments / <b>{{folderName}}</b>
|
||||
</h4>
|
||||
|
||||
<ul v-if="!isLoading" class="nav-links">
|
||||
<li v-bind:class="{ 'active': scope === undefined || scope === 'available' }">
|
||||
<a :href="availablePath">
|
||||
<ul class="nav-links">
|
||||
<li v-bind:class="{ 'active': scope === null || scope === 'available' }">
|
||||
<a :href="availablePath" class="js-available-environments-folder-tab">
|
||||
Available
|
||||
<span class="badge js-available-environments-count">
|
||||
{{state.availableCounter}}
|
||||
|
@ -157,7 +142,7 @@ module.exports = Vue.component('environment-folder-view', {
|
|||
</a>
|
||||
</li>
|
||||
<li v-bind:class="{ 'active' : scope === 'stopped' }">
|
||||
<a :href="stoppedPath">
|
||||
<a :href="stoppedPath" class="js-stopped-environments-folder-tab">
|
||||
Stopped
|
||||
<span class="badge js-stopped-environments-count">
|
||||
{{state.stoppedCounter}}
|
||||
|
|
|
@ -241,5 +241,45 @@
|
|||
acc[element] = DOMStringMapObject[element];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* Updates the search parameter of a URL given the parameter and values provided.
|
||||
*
|
||||
* If no search params are present we'll add it.
|
||||
* If param for page is already present, we'll update it
|
||||
* If there are params but not for the given one, we'll add it at the end.
|
||||
* Returns the new search parameters.
|
||||
*
|
||||
* @param {String} param
|
||||
* @param {Number|String|Undefined|Null} value
|
||||
* @return {String}
|
||||
*/
|
||||
w.gl.utils.setParamInURL = (param, value) => {
|
||||
let search;
|
||||
|
||||
if (window.location.search.length === 0) {
|
||||
search = `?${param}=${value}`;
|
||||
}
|
||||
|
||||
if (window.location.search.indexOf(param) !== -1) {
|
||||
const regex = new RegExp(param + '=\\d');
|
||||
search = window.location.search.replace(regex, `${param}=${value}`);
|
||||
}
|
||||
|
||||
if (window.location.search.length &&
|
||||
window.location.search.indexOf(param) === -1) {
|
||||
search = `${window.location.search}&${param}=${value}`;
|
||||
}
|
||||
|
||||
return search;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts permission provided as strings to booleans.
|
||||
*
|
||||
* @param {String} string
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
w.gl.utils.convertPermissionToBoolean = permission => permission === 'true';
|
||||
})(window);
|
||||
}).call(this);
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
font-size: 34px;
|
||||
}
|
||||
|
||||
.environments-folder-name {
|
||||
font-weight: normal;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
.environments-container {
|
||||
width: 100%;
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
const EnvironmentTable = require('~/environments/components/environments_table');
|
||||
|
||||
describe('Environment item', () => {
|
||||
preloadFixtures('static/environments/element.html.raw');
|
||||
beforeEach(() => {
|
||||
loadFixtures('static/environments/element.html.raw');
|
||||
});
|
||||
|
||||
it('Should render a table', () => {
|
||||
const mockItem = {
|
||||
name: 'review',
|
||||
size: 3,
|
||||
isFolder: true,
|
||||
latest: {
|
||||
environment_path: 'url',
|
||||
},
|
||||
};
|
||||
|
||||
const component = new EnvironmentTable({
|
||||
el: document.querySelector('.test-dom-element'),
|
||||
propsData: {
|
||||
environments: [{ mockItem }],
|
||||
canCreateDeployment: false,
|
||||
canReadEnvironment: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(component.$el.tagName).toEqual('TABLE');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,212 @@
|
|||
const Vue = require('vue');
|
||||
require('~/flash');
|
||||
const EnvironmentsFolderViewComponent = require('~/environments/folder/environments_folder_view');
|
||||
const { environmentsList } = require('../mock_data');
|
||||
|
||||
describe('Environments Folder View', () => {
|
||||
preloadFixtures('static/environments/environments_folder_view.html.raw');
|
||||
|
||||
beforeEach(() => {
|
||||
loadFixtures('static/environments/environments_folder_view.html.raw');
|
||||
window.history.pushState({}, null, 'environments/folders/51');
|
||||
});
|
||||
|
||||
let component;
|
||||
|
||||
describe('successfull request', () => {
|
||||
const environmentsResponseInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify({
|
||||
environments: environmentsList,
|
||||
stopped_count: 1,
|
||||
available_count: 0,
|
||||
}), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'X-nExt-pAge': '2',
|
||||
'x-page': '1',
|
||||
'X-Per-Page': '1',
|
||||
'X-Prev-Page': '',
|
||||
'X-TOTAL': '37',
|
||||
'X-Total-Pages': '2',
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(environmentsResponseInterceptor);
|
||||
component = new EnvironmentsFolderViewComponent({
|
||||
el: document.querySelector('#environments-folder-list-view'),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(
|
||||
Vue.http.interceptors, environmentsResponseInterceptor,
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a table with environments', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelectorAll('table tbody tr').length,
|
||||
).toEqual(2);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render available tab with count', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-available-environments-folder-tab').textContent,
|
||||
).toContain('Available');
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render stopped tab with count', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-stopped-environments-folder-tab').textContent,
|
||||
).toContain('Stopped');
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent,
|
||||
).toContain('1');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// FIX ME:
|
||||
it('should render parent folder name', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-folder-name'),
|
||||
).toBe(null);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
describe('pagination', () => {
|
||||
it('should render pagination', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelectorAll('.gl-pagination li').length,
|
||||
).toEqual(5);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should update url when no search params are present', (done) => {
|
||||
spyOn(gl.utils, 'visitUrl');
|
||||
setTimeout(() => {
|
||||
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
|
||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should update url when page is already present', (done) => {
|
||||
spyOn(gl.utils, 'visitUrl');
|
||||
window.history.pushState({}, null, '?page=1');
|
||||
|
||||
setTimeout(() => {
|
||||
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
|
||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should update url when page and scope are already present', (done) => {
|
||||
spyOn(gl.utils, 'visitUrl');
|
||||
window.history.pushState({}, null, '?scope=all&page=1');
|
||||
|
||||
setTimeout(() => {
|
||||
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
|
||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?scope=all&page=2');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should update url when page and scope are already present and page is first param', (done) => {
|
||||
spyOn(gl.utils, 'visitUrl');
|
||||
window.history.pushState({}, null, '?page=1&scope=all');
|
||||
|
||||
setTimeout(() => {
|
||||
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
|
||||
expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2&scope=all');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('unsuccessfull request', () => {
|
||||
const environmentsErrorResponseInterceptor = (request, next) => {
|
||||
next(request.respondWith(JSON.stringify([]), {
|
||||
status: 500,
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
Vue.http.interceptors.push(environmentsErrorResponseInterceptor);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
Vue.http.interceptors = _.without(
|
||||
Vue.http.interceptors, environmentsErrorResponseInterceptor,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render a table', (done) => {
|
||||
component = new EnvironmentsFolderViewComponent({
|
||||
el: document.querySelector('#environments-folder-list-view'),
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('table'),
|
||||
).toBe(null);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render available tab with count 0', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-available-environments-folder-tab').textContent,
|
||||
).toContain('Available');
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render stopped tab with count 0', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-stopped-environments-folder-tab').textContent,
|
||||
).toContain('Stopped');
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should not render parent folder name', (done) => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
component.$el.querySelector('.js-folder-name'),
|
||||
).toBe(null);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
%div
|
||||
#environments-folder-list-view{ data: { "can-create-deployment" => "true",
|
||||
"can-read-environment" => "true",
|
||||
"css-class" => "",
|
||||
"commit-icon-svg" => custom_icon("icon_commit"),
|
||||
"terminal-icon-svg" => custom_icon("icon_terminal"),
|
||||
"play-icon-svg" => custom_icon("icon_play") } }
|
Loading…
Reference in New Issue