From f4fb0340094508106113c0c7c22c865fa7c73f7f Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Mon, 6 Nov 2017 10:07:19 -0600 Subject: Add FE tests for not_installable/scheduled and cluster banner rules --- app/assets/javascripts/clusters/clusters_bundle.js | 48 +++++++++++++--------- .../clusters/components/application_row.vue | 6 ++- app/assets/javascripts/clusters/constants.js | 2 +- .../clusters/services/clusters_service.js | 2 + spec/javascripts/clusters/clusters_bundle_spec.js | 48 ++++++++++++++++++++-- .../clusters/components/application_row_spec.js | 42 +++++++++++++++---- .../clusters/stores/clusters_store_spec.js | 3 ++ 7 files changed, 117 insertions(+), 34 deletions(-) diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 4d4c90460d2..c486208175f 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -28,6 +28,8 @@ export default class Clusters { const { statusPath, installHelmPath, + installIngressPath, + installRunnerPath, clusterStatus, clusterStatusReason, helpPath, @@ -40,6 +42,8 @@ export default class Clusters { this.service = new ClustersService({ endpoint: statusPath, installHelmEndpoint: installHelmPath, + installIngresEndpoint: installIngressPath, + installRunnerEndpoint: installRunnerPath, }); this.toggle = this.toggle.bind(this); @@ -57,7 +61,7 @@ export default class Clusters { this.initApplications(); if (this.store.state.status !== 'created') { - this.updateContainer(this.store.state.status, this.store.state.statusReason); + this.updateContainer(null, this.store.state.status, this.store.state.statusReason); } this.addListeners(); @@ -131,13 +135,13 @@ export default class Clusters { } handleSuccess(data) { - const prevApplicationMap = Object.assign({}, this.store.state.applications); const prevStatus = this.store.state.status; + const prevApplicationMap = Object.assign({}, this.store.state.applications); + this.store.updateStateFromServer(data.data); + this.checkForNewInstalls(prevApplicationMap, this.store.state.applications); - if (prevStatus.length == 0 || prevStatus !== this.store.state.status) { - this.updateContainer(this.store.state.status, this.store.state.statusReason); - } + this.updateContainer(prevStatus, this.store.state.status, this.store.state.statusReason); } toggle() { @@ -168,22 +172,26 @@ export default class Clusters { } } - updateContainer(status, error) { + updateContainer(prevStatus, status, error) { this.hideAll(); - switch (status) { - case 'created': - this.successContainer.classList.remove('hidden'); - break; - case 'errored': - this.errorContainer.classList.remove('hidden'); - this.errorReasonContainer.textContent = error; - break; - case 'scheduled': - case 'creating': - this.creatingContainer.classList.remove('hidden'); - break; - default: - this.hideAll(); + + // We poll all the time but only want the `created` banner to show when newly created + if (this.store.state.status !== 'created' || prevStatus !== this.store.state.status) { + switch (status) { + case 'created': + this.successContainer.classList.remove('hidden'); + break; + case 'errored': + this.errorContainer.classList.remove('hidden'); + this.errorReasonContainer.textContent = error; + break; + case 'scheduled': + case 'creating': + this.creatingContainer.classList.remove('hidden'); + break; + default: + this.hideAll(); + } } } diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index 9c5ff39534f..3dc658d0f1f 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -75,7 +75,11 @@ export default { }, installButtonLabel() { let label; - if (this.status === APPLICATION_INSTALLABLE || this.status === APPLICATION_ERROR || this.status === APPLICATION_NOT_INSTALLABLE) { + if ( + this.status === APPLICATION_NOT_INSTALLABLE || + this.status === APPLICATION_INSTALLABLE || + this.status === APPLICATION_ERROR + ) { label = s__('ClusterIntegration|Install'); } else if (this.status === APPLICATION_SCHEDULED || this.status === APPLICATION_INSTALLING) { label = s__('ClusterIntegration|Installing'); diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js index f1894b173b9..93223aefff8 100644 --- a/app/assets/javascripts/clusters/constants.js +++ b/app/assets/javascripts/clusters/constants.js @@ -4,7 +4,7 @@ export const APPLICATION_INSTALLABLE = 'installable'; export const APPLICATION_SCHEDULED = 'scheduled'; export const APPLICATION_INSTALLING = 'installing'; export const APPLICATION_INSTALLED = 'installed'; -export const APPLICATION_ERROR = 'error'; +export const APPLICATION_ERROR = 'errored'; // These are only used client-side export const REQUEST_LOADING = 'request-loading'; diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index a7bb0961c7e..0ac8e68187d 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -8,6 +8,8 @@ export default class ClusterService { this.options = options; this.appInstallEndpointMap = { helm: this.options.installHelmEndpoint, + ingress: this.options.installIngressEndpoint, + runner: this.options.installRunnerEndpoint, }; } diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js index 26d230ce414..86e9cb22be8 100644 --- a/spec/javascripts/clusters/clusters_bundle_spec.js +++ b/spec/javascripts/clusters/clusters_bundle_spec.js @@ -104,7 +104,21 @@ describe('Clusters', () => { describe('updateContainer', () => { describe('when creating cluster', () => { it('should show the creating container', () => { - cluster.updateContainer('creating'); + cluster.updateContainer(null, 'creating'); + + expect( + cluster.creatingContainer.classList.contains('hidden'), + ).toBeFalsy(); + expect( + cluster.successContainer.classList.contains('hidden'), + ).toBeTruthy(); + expect( + cluster.errorContainer.classList.contains('hidden'), + ).toBeTruthy(); + }); + + it('should continue to show `creating` banner with subsequent updates of the same status', () => { + cluster.updateContainer('creating', 'creating'); expect( cluster.creatingContainer.classList.contains('hidden'), @@ -120,7 +134,7 @@ describe('Clusters', () => { describe('when cluster is created', () => { it('should show the success container', () => { - cluster.updateContainer('created'); + cluster.updateContainer(null, 'created'); expect( cluster.creatingContainer.classList.contains('hidden'), @@ -132,11 +146,25 @@ describe('Clusters', () => { cluster.errorContainer.classList.contains('hidden'), ).toBeTruthy(); }); + + it('should not show a banner when status is already `created`', () => { + cluster.updateContainer('created', 'created'); + + expect( + cluster.creatingContainer.classList.contains('hidden'), + ).toBeTruthy(); + expect( + cluster.successContainer.classList.contains('hidden'), + ).toBeTruthy(); + expect( + cluster.errorContainer.classList.contains('hidden'), + ).toBeTruthy(); + }); }); describe('when cluster has error', () => { it('should show the error container', () => { - cluster.updateContainer('errored', 'this is an error'); + cluster.updateContainer(null, 'errored', 'this is an error'); expect( cluster.creatingContainer.classList.contains('hidden'), @@ -152,6 +180,20 @@ describe('Clusters', () => { cluster.errorReasonContainer.textContent, ).toContain('this is an error'); }); + + it('should show `error` banner when previously `creating`', () => { + cluster.updateContainer('creating', 'errored'); + + expect( + cluster.creatingContainer.classList.contains('hidden'), + ).toBeTruthy(); + expect( + cluster.successContainer.classList.contains('hidden'), + ).toBeTruthy(); + expect( + cluster.errorContainer.classList.contains('hidden'), + ).toBeFalsy(); + }); }); }); diff --git a/spec/javascripts/clusters/components/application_row_spec.js b/spec/javascripts/clusters/components/application_row_spec.js index ba38ed6f180..392cebc5e35 100644 --- a/spec/javascripts/clusters/components/application_row_spec.js +++ b/spec/javascripts/clusters/components/application_row_spec.js @@ -1,6 +1,8 @@ import Vue from 'vue'; import eventHub from '~/clusters/event_hub'; import { + APPLICATION_NOT_INSTALLABLE, + APPLICATION_SCHEDULED, APPLICATION_INSTALLABLE, APPLICATION_INSTALLING, APPLICATION_INSTALLED, @@ -60,7 +62,18 @@ describe('Application Row', () => { expect(vm.installButtonLabel).toBeUndefined(); }); - it('has enabled "Install" when `status=installable`', () => { + it('has disabled "Install" when APPLICATION_NOT_INSTALLABLE', () => { + vm = mountComponent(ApplicationRow, { + ...DEFAULT_APPLICATION_STATE, + status: APPLICATION_NOT_INSTALLABLE, + }); + + expect(vm.installButtonLabel).toEqual('Install'); + expect(vm.installButtonLoading).toEqual(false); + expect(vm.installButtonDisabled).toEqual(true); + }); + + it('has enabled "Install" when APPLICATION_INSTALLABLE', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLABLE, @@ -71,7 +84,18 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(false); }); - it('has loading "Installing" when `status=installing`', () => { + it('has loading "Installing" when APPLICATION_SCHEDULED', () => { + vm = mountComponent(ApplicationRow, { + ...DEFAULT_APPLICATION_STATE, + status: APPLICATION_SCHEDULED, + }); + + expect(vm.installButtonLabel).toEqual('Installing'); + expect(vm.installButtonLoading).toEqual(true); + expect(vm.installButtonDisabled).toEqual(true); + }); + + it('has loading "Installing" when APPLICATION_INSTALLING', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLING, @@ -82,7 +106,7 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Installed" when `status=installed`', () => { + it('has disabled "Installed" when APPLICATION_INSTALLED', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLED, @@ -93,7 +117,7 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Install" when `status=error`', () => { + it('has disabled "Install" when APPLICATION_ERROR', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_ERROR, @@ -104,7 +128,7 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has loading "Install" when `requestStatus=loading`', () => { + it('has loading "Install" when REQUEST_LOADING', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLABLE, @@ -116,7 +140,7 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has disabled "Install" when `requestStatus=success`', () => { + it('has disabled "Install" when REQUEST_SUCCESS', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLABLE, @@ -128,7 +152,7 @@ describe('Application Row', () => { expect(vm.installButtonDisabled).toEqual(true); }); - it('has enabled "Install" when `requestStatus=error` (so you can try installing again)', () => { + it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => { vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, status: APPLICATION_INSTALLABLE, @@ -181,7 +205,7 @@ describe('Application Row', () => { expect(generalErrorMessage).toBeNull(); }); - it('shows status reason when `status=error`', () => { + it('shows status reason when APPLICATION_ERROR', () => { const statusReason = 'We broke it 0.0'; vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, @@ -195,7 +219,7 @@ describe('Application Row', () => { expect(statusErrorMessage.textContent.trim()).toEqual(statusReason); }); - it('shows request reason when `requestStatus=error`', () => { + it('shows request reason when REQUEST_FAILURE', () => { const requestReason = 'We broke thre request 0.0'; vm = mountComponent(ApplicationRow, { ...DEFAULT_APPLICATION_STATE, diff --git a/spec/javascripts/clusters/stores/clusters_store_spec.js b/spec/javascripts/clusters/stores/clusters_store_spec.js index 9f9d63434f7..cb8b3d38e2e 100644 --- a/spec/javascripts/clusters/stores/clusters_store_spec.js +++ b/spec/javascripts/clusters/stores/clusters_store_spec.js @@ -62,18 +62,21 @@ describe('Clusters Store', () => { statusReason: mockResponseData.status_reason, applications: { helm: { + title: 'Helm Tiller', status: mockResponseData.applications[0].status, statusReason: mockResponseData.applications[0].status_reason, requestStatus: null, requestReason: null, }, ingress: { + title: 'Ingress', status: mockResponseData.applications[1].status, statusReason: mockResponseData.applications[1].status_reason, requestStatus: null, requestReason: null, }, runner: { + title: 'GitLab Runner', status: mockResponseData.applications[2].status, statusReason: mockResponseData.applications[2].status_reason, requestStatus: null, -- cgit v1.2.1