diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2017-11-23 12:04:03 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-11-23 12:04:03 +0000 |
commit | 45631562565760add7a7c52a6137e891f3a0c8f4 (patch) | |
tree | 44915f7c46d05fb8c6197662a3341ea8fb610f06 /spec/javascripts/environments | |
parent | 1d8ab59ebfa0d57e4015665c470c8339cd258a2c (diff) | |
download | gitlab-ce-45631562565760add7a7c52a6137e891f3a0c8f4.tar.gz |
Improve environments performance
Diffstat (limited to 'spec/javascripts/environments')
-rw-r--r-- | spec/javascripts/environments/emtpy_state_spec.js | 57 | ||||
-rw-r--r-- | spec/javascripts/environments/environment_table_spec.js | 31 | ||||
-rw-r--r-- | spec/javascripts/environments/environments_app_spec.js (renamed from spec/javascripts/environments/environment_spec.js) | 132 | ||||
-rw-r--r-- | spec/javascripts/environments/folder/environments_folder_view_spec.js | 157 |
4 files changed, 247 insertions, 130 deletions
diff --git a/spec/javascripts/environments/emtpy_state_spec.js b/spec/javascripts/environments/emtpy_state_spec.js new file mode 100644 index 00000000000..82de35933f5 --- /dev/null +++ b/spec/javascripts/environments/emtpy_state_spec.js @@ -0,0 +1,57 @@ + +import Vue from 'vue'; +import emptyState from '~/environments/components/empty_state.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('environments empty state', () => { + let vm; + let Component; + + beforeEach(() => { + Component = Vue.extend(emptyState); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('With permissions', () => { + beforeEach(() => { + vm = mountComponent(Component, { + newPath: 'foo', + canCreateEnvironment: true, + helpPath: 'bar', + }); + }); + + it('renders empty state and new environment button', () => { + expect( + vm.$el.querySelector('.js-blank-state-title').textContent.trim(), + ).toEqual('You don\'t have any environments right now.'); + + expect( + vm.$el.querySelector('.js-new-environment-button').getAttribute('href'), + ).toEqual('foo'); + }); + }); + + describe('Without permission', () => { + beforeEach(() => { + vm = mountComponent(Component, { + newPath: 'foo', + canCreateEnvironment: false, + helpPath: 'bar', + }); + }); + + it('renders empty state without new button', () => { + expect( + vm.$el.querySelector('.js-blank-state-title').textContent.trim(), + ).toEqual('You don\'t have any environments right now.'); + + expect( + vm.$el.querySelector('.js-new-environment-button'), + ).toBeNull(); + }); + }); +}); diff --git a/spec/javascripts/environments/environment_table_spec.js b/spec/javascripts/environments/environment_table_spec.js index 2862971bec4..9bd42863759 100644 --- a/spec/javascripts/environments/environment_table_spec.js +++ b/spec/javascripts/environments/environment_table_spec.js @@ -1,10 +1,17 @@ import Vue from 'vue'; import environmentTableComp from '~/environments/components/environments_table.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('Environment table', () => { + let Component; + let vm; -describe('Environment item', () => { - preloadFixtures('static/environments/element.html.raw'); beforeEach(() => { - loadFixtures('static/environments/element.html.raw'); + Component = Vue.extend(environmentTableComp); + }); + + afterEach(() => { + vm.$destroy(); }); it('Should render a table', () => { @@ -17,18 +24,12 @@ describe('Environment item', () => { }, }; - const EnvironmentTable = Vue.extend(environmentTableComp); - - const component = new EnvironmentTable({ - el: document.querySelector('.test-dom-element'), - propsData: { - environments: [{ mockItem }], - canCreateDeployment: false, - canReadEnvironment: true, - service: {}, - }, - }).$mount(); + vm = mountComponent(Component, { + environments: [mockItem], + canCreateDeployment: false, + canReadEnvironment: true, + }); - expect(component.$el.getAttribute('class')).toContain('ci-table'); + expect(vm.$el.getAttribute('class')).toContain('ci-table'); }); }); diff --git a/spec/javascripts/environments/environment_spec.js b/spec/javascripts/environments/environments_app_spec.js index 0c8817a8148..d02adb25b4e 100644 --- a/spec/javascripts/environments/environment_spec.js +++ b/spec/javascripts/environments/environments_app_spec.js @@ -1,18 +1,24 @@ import Vue from 'vue'; -import '~/flash'; -import environmentsComponent from '~/environments/components/environment.vue'; +import environmentsComponent from '~/environments/components/environments_app.vue'; import { environment, folder } from './mock_data'; import { headersInterceptor } from '../helpers/vue_resource_helper'; +import mountComponent from '../helpers/vue_mount_component_helper'; describe('Environment', () => { - preloadFixtures('static/environments/environments.html.raw'); + const mockData = { + endpoint: 'environments.json', + canCreateEnvironment: true, + canCreateDeployment: true, + canReadEnvironment: true, + cssContainerClass: 'container', + newEnvironmentPath: 'environments/new', + helpPagePath: 'help', + }; let EnvironmentsComponent; let component; beforeEach(() => { - loadFixtures('static/environments/environments.html.raw'); - EnvironmentsComponent = Vue.extend(environmentsComponent); }); @@ -37,9 +43,7 @@ describe('Environment', () => { }); it('should render the empty state', (done) => { - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); setTimeout(() => { expect( @@ -81,9 +85,7 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); Vue.http.interceptors.push(headersInterceptor); - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); }); afterEach(() => { @@ -95,7 +97,7 @@ describe('Environment', () => { it('should render a table with environments', (done) => { setTimeout(() => { - expect(component.$el.querySelectorAll('table')).toBeDefined(); + expect(component.$el.querySelectorAll('table')).not.toBeNull(); expect( component.$el.querySelector('.environment-name').textContent.trim(), ).toEqual(environment.name); @@ -104,10 +106,6 @@ describe('Environment', () => { }); describe('pagination', () => { - afterEach(() => { - window.history.pushState({}, null, ''); - }); - it('should render pagination', (done) => { setTimeout(() => { expect( @@ -117,46 +115,23 @@ describe('Environment', () => { }, 0); }); - it('should update url when no search params are present', (done) => { - spyOn(gl.utils, 'visitUrl'); + it('should make an API request when page is clicked', (done) => { + spyOn(component, 'updateContent'); setTimeout(() => { component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', 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'); - + it('should make an API request when using tabs', (done) => { setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?scope=all&page=2'); - done(); - }, 0); - }); + spyOn(component, 'updateContent'); + component.$el.querySelector('.js-environments-tab-stopped').click(); - 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'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); done(); - }, 0); + }); }); }); }); @@ -180,9 +155,7 @@ describe('Environment', () => { }); it('should render empty state', (done) => { - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); setTimeout(() => { expect( @@ -214,9 +187,7 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); }); afterEach(() => { @@ -289,4 +260,59 @@ describe('Environment', () => { }); }); }); + + describe('methods', () => { + const environmentsEmptyResponseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(environmentsEmptyResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); + + component = mountComponent(EnvironmentsComponent, mockData); + spyOn(history, 'pushState').and.stub(); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, environmentsEmptyResponseInterceptor, + ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); + }); + + describe('updateContent', () => { + it('should set given parameters', (done) => { + component.updateContent({ scope: 'stopped', page: '3' }) + .then(() => { + expect(component.page).toEqual('3'); + expect(component.scope).toEqual('stopped'); + expect(component.requestData.scope).toEqual('stopped'); + expect(component.requestData.page).toEqual('3'); + done(); + }) + .catch(done.fail); + }); + }); + + describe('onChangeTab', () => { + it('should set page to 1', () => { + spyOn(component, 'updateContent'); + component.onChangeTab('stopped'); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); + }); + }); + + describe('onChangePage', () => { + it('should update page and keep scope', () => { + spyOn(component, 'updateContent'); + component.onChangePage(4); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + }); + }); + }); }); diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js index 7e62d356bd2..4ea4d9d7499 100644 --- a/spec/javascripts/environments/folder/environments_folder_view_spec.js +++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js @@ -1,25 +1,28 @@ import Vue from 'vue'; -import '~/flash'; import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue'; import { environmentsList } from '../mock_data'; import { headersInterceptor } from '../../helpers/vue_resource_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Environments Folder View', () => { - preloadFixtures('static/environments/environments_folder_view.html.raw'); - let EnvironmentsFolderViewComponent; + let Component; + let component; + const mockData = { + endpoint: 'environments.json', + folderName: 'review', + canCreateDeployment: true, + canReadEnvironment: true, + cssContainerClass: 'container', + }; beforeEach(() => { - loadFixtures('static/environments/environments_folder_view.html.raw'); - EnvironmentsFolderViewComponent = Vue.extend(environmentsFolderViewComponent); - window.history.pushState({}, null, 'environments/folders/build'); + Component = Vue.extend(environmentsFolderViewComponent); }); afterEach(() => { - window.history.pushState({}, null, '/'); + component.$destroy(); }); - let component; - describe('successfull request', () => { const environmentsResponseInterceptor = (request, next) => { next(request.respondWith(JSON.stringify({ @@ -31,10 +34,10 @@ describe('Environments Folder View', () => { headers: { 'X-nExt-pAge': '2', 'x-page': '1', - 'X-Per-Page': '1', + 'X-Per-Page': '2', 'X-Prev-Page': '', - 'X-TOTAL': '37', - 'X-Total-Pages': '2', + 'X-TOTAL': '20', + 'X-Total-Pages': '10', }, })); }; @@ -43,9 +46,7 @@ describe('Environments Folder View', () => { Vue.http.interceptors.push(environmentsResponseInterceptor); Vue.http.interceptors.push(headersInterceptor); - component = new EnvironmentsFolderViewComponent({ - el: document.querySelector('#environments-folder-list-view'), - }); + component = mountComponent(Component, mockData); }); afterEach(() => { @@ -57,7 +58,7 @@ describe('Environments Folder View', () => { it('should render a table with environments', (done) => { setTimeout(() => { - expect(component.$el.querySelectorAll('table')).toBeDefined(); + expect(component.$el.querySelectorAll('table')).not.toBeNull(); expect( component.$el.querySelector('.environment-name').textContent.trim(), ).toEqual(environmentsList[0].name); @@ -68,11 +69,11 @@ describe('Environments Folder View', () => { it('should render available tab with count', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-available-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-available').textContent, ).toContain('Available'); expect( - component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-available .badge').textContent, ).toContain('0'); done(); }, 0); @@ -81,11 +82,11 @@ describe('Environments Folder View', () => { it('should render stopped tab with count', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-stopped-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-stopped').textContent, ).toContain('Stopped'); expect( - component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-stopped .badge').textContent, ).toContain('1'); done(); }, 0); @@ -94,8 +95,8 @@ describe('Environments Folder View', () => { it('should render parent folder name', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-folder-name').textContent, - ).toContain('Environments / build'); + component.$el.querySelector('.js-folder-name').textContent.trim(), + ).toContain('Environments / review'); done(); }, 0); }); @@ -104,52 +105,30 @@ describe('Environments Folder View', () => { it('should render pagination', (done) => { setTimeout(() => { expect( - component.$el.querySelectorAll('.gl-pagination li').length, - ).toEqual(5); + component.$el.querySelectorAll('.gl-pagination'), + ).not.toBeNull(); done(); }, 0); }); - it('should update url when no search params are present', (done) => { - spyOn(gl.utils, 'visitUrl'); + it('should make an API request when changing page', (done) => { + spyOn(component, 'updateContent'); 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'); + component.$el.querySelector('.gl-pagination .js-last-button a').click(); - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '10' }); 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'); - + it('should make an API request when using tabs', (done) => { 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'); + spyOn(component, 'updateContent'); + component.$el.querySelector('.js-environments-tab-stopped').click(); - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2&scope=all'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); done(); - }, 0); + }); }); }); }); @@ -172,9 +151,7 @@ describe('Environments Folder View', () => { }); it('should not render a table', (done) => { - component = new EnvironmentsFolderViewComponent({ - el: document.querySelector('#environments-folder-list-view'), - }); + component = mountComponent(Component, mockData); setTimeout(() => { expect( @@ -187,11 +164,11 @@ describe('Environments Folder View', () => { it('should render available tab with count 0', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-available-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-available').textContent, ).toContain('Available'); expect( - component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-available .badge').textContent, ).toContain('0'); done(); }, 0); @@ -200,14 +177,70 @@ describe('Environments Folder View', () => { it('should render stopped tab with count 0', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-stopped-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-stopped').textContent, ).toContain('Stopped'); expect( - component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-stopped .badge').textContent, ).toContain('0'); done(); }, 0); }); }); + + describe('methods', () => { + const environmentsEmptyResponseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(environmentsEmptyResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); + + component = mountComponent(Component, mockData); + spyOn(history, 'pushState').and.stub(); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, environmentsEmptyResponseInterceptor, + ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); + }); + + describe('updateContent', () => { + it('should set given parameters', (done) => { + component.updateContent({ scope: 'stopped', page: '4' }) + .then(() => { + expect(component.page).toEqual('4'); + expect(component.scope).toEqual('stopped'); + expect(component.requestData.scope).toEqual('stopped'); + expect(component.requestData.page).toEqual('4'); + done(); + }) + .catch(done.fail); + }); + }); + + describe('onChangeTab', () => { + it('should set page to 1', () => { + spyOn(component, 'updateContent'); + component.onChangeTab('stopped'); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); + }); + }); + + describe('onChangePage', () => { + it('should update page and keep scope', () => { + spyOn(component, 'updateContent'); + + component.onChangePage(4); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + }); + }); + }); }); |