summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-02-13 16:11:11 +0000
committerFilipa Lacerda <filipa@gitlab.com>2017-02-15 19:57:48 +0000
commit1285d629064abce3aee8faafaa57492da6f8f163 (patch)
tree29f6e73839bd7fadfd7f98a0223b955b2c0165c6
parent73accafe430f56cd3065774c6118de3db0a45734 (diff)
downloadgitlab-ce-1285d629064abce3aee8faafaa57492da6f8f163.tar.gz
Move change page param to utility function
Add tests Adds folder name in the top of the table
-rw-r--r--app/assets/javascripts/environments/components/environment.js.es634
-rw-r--r--app/assets/javascripts/environments/components/environment_item.js.es64
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js.es61
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.js.es667
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js.es640
-rw-r--r--app/assets/stylesheets/pages/environments.scss5
-rw-r--r--spec/javascripts/environments/environment_table_spec.js.es630
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js.es6212
-rw-r--r--spec/javascripts/fixtures/environments/environments_folder_view.html.haml7
9 files changed, 328 insertions, 72 deletions
diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js.es6
index 2cbfbcad023..e9ea6d91adb 100644
--- a/app/assets/javascripts/environments/components/environment.js.es6
+++ b/app/assets/javascripts/environments/components/environment.js.es6
@@ -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;
diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js.es6
index e40c97130ad..8401459977b 100644
--- a/app/assets/javascripts/environments/components/environment_item.js.es6
+++ b/app/assets/javascripts/environments/components/environment_item.js.es6
@@ -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}`;
},
},
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
index d2ca465351a..29f704c1a37 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js.es6
@@ -1,4 +1,5 @@
const EnvironmentsFolderComponent = require('./environments_folder_view');
+require('../../vue_shared/vue_resource_interceptor');
$(() => {
window.gl = window.gl || {};
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6 b/app/assets/javascripts/environments/folder/environments_folder_view.js.es6
index c5d1e2d4d9f..f67e5eab64a 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.js.es6
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.js.es6
@@ -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}}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js.es6 b/app/assets/javascripts/lib/utils/common_utils.js.es6
index bcb3a706b51..276ff01ab89 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js.es6
+++ b/app/assets/javascripts/lib/utils/common_utils.js.es6
@@ -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);
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 2f4a3c80aeb..fed63158f41 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -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%;
diff --git a/spec/javascripts/environments/environment_table_spec.js.es6 b/spec/javascripts/environments/environment_table_spec.js.es6
new file mode 100644
index 00000000000..be4330b5012
--- /dev/null
+++ b/spec/javascripts/environments/environment_table_spec.js.es6
@@ -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');
+ });
+});
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js.es6 b/spec/javascripts/environments/folder/environments_folder_view_spec.js.es6
new file mode 100644
index 00000000000..6a95fabcea5
--- /dev/null
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js.es6
@@ -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);
+ });
+ });
+});
diff --git a/spec/javascripts/fixtures/environments/environments_folder_view.html.haml b/spec/javascripts/fixtures/environments/environments_folder_view.html.haml
new file mode 100644
index 00000000000..aceec139730
--- /dev/null
+++ b/spec/javascripts/fixtures/environments/environments_folder_view.html.haml
@@ -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") } }