Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/clusters')
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js376
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js406
-rw-r--r--spec/frontend/clusters/components/applications_spec.js350
-rw-r--r--spec/frontend/clusters/services/mock_data.js130
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js142
5 files changed, 1404 insertions, 0 deletions
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
new file mode 100644
index 00000000000..eea7bd87257
--- /dev/null
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -0,0 +1,376 @@
+import Clusters from '~/clusters/clusters_bundle';
+import {
+ REQUEST_SUBMITTED,
+ REQUEST_FAILURE,
+ APPLICATION_STATUS,
+ INGRESS_DOMAIN_SUFFIX,
+} from '~/clusters/constants';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { loadHTMLFixture } from 'helpers/fixtures';
+import { setTestTimeout } from 'helpers/timeout';
+import $ from 'jquery';
+
+describe('Clusters', () => {
+ setTestTimeout(500);
+
+ let cluster;
+ let mock;
+
+ const mockGetClusterStatusRequest = () => {
+ const { statusPath } = document.querySelector('.js-edit-cluster-form').dataset;
+
+ mock = new MockAdapter(axios);
+
+ mock.onGet(statusPath).reply(200);
+ };
+
+ beforeEach(() => {
+ loadHTMLFixture('clusters/show_cluster.html');
+ });
+
+ beforeEach(() => {
+ mockGetClusterStatusRequest();
+ });
+
+ beforeEach(() => {
+ cluster = new Clusters();
+ });
+
+ afterEach(() => {
+ cluster.destroy();
+ mock.restore();
+ });
+
+ describe('toggle', () => {
+ it('should update the button and the input field on click', done => {
+ const toggleButton = document.querySelector(
+ '.js-cluster-enable-toggle-area .js-project-feature-toggle',
+ );
+ const toggleInput = document.querySelector(
+ '.js-cluster-enable-toggle-area .js-project-feature-toggle-input',
+ );
+
+ $(toggleInput).one('trigger-change', () => {
+ expect(toggleButton.classList).not.toContain('is-checked');
+ expect(toggleInput.getAttribute('value')).toEqual('false');
+ done();
+ });
+
+ toggleButton.click();
+ });
+ });
+
+ describe('showToken', () => {
+ it('should update token field type', () => {
+ cluster.showTokenButton.click();
+
+ expect(cluster.tokenField.getAttribute('type')).toEqual('text');
+
+ cluster.showTokenButton.click();
+
+ expect(cluster.tokenField.getAttribute('type')).toEqual('password');
+ });
+
+ it('should update show token button text', () => {
+ cluster.showTokenButton.click();
+
+ expect(cluster.showTokenButton.textContent).toEqual('Hide');
+
+ cluster.showTokenButton.click();
+
+ expect(cluster.showTokenButton.textContent).toEqual('Show');
+ });
+ });
+
+ describe('checkForNewInstalls', () => {
+ const INITIAL_APP_MAP = {
+ helm: { status: null, title: 'Helm Tiller' },
+ ingress: { status: null, title: 'Ingress' },
+ runner: { status: null, title: 'GitLab Runner' },
+ };
+
+ it('does not show alert when things transition from initial null state to something', () => {
+ cluster.checkForNewInstalls(INITIAL_APP_MAP, {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Helm Tiller' },
+ });
+
+ const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
+ expect(flashMessage).toBeNull();
+ });
+
+ it('shows an alert when something gets newly installed', () => {
+ cluster.checkForNewInstalls(
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
+ },
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
+ },
+ );
+
+ const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
+ expect(flashMessage).not.toBeNull();
+ expect(flashMessage.textContent.trim()).toEqual(
+ 'Helm Tiller was successfully installed on your Kubernetes cluster',
+ );
+ });
+
+ it('shows an alert when multiple things gets newly installed', () => {
+ cluster.checkForNewInstalls(
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
+ ingress: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Ingress' },
+ },
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
+ ingress: { status: APPLICATION_STATUS.INSTALLED, title: 'Ingress' },
+ },
+ );
+
+ const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
+ expect(flashMessage).not.toBeNull();
+ expect(flashMessage.textContent.trim()).toEqual(
+ 'Helm Tiller, Ingress was successfully installed on your Kubernetes cluster',
+ );
+ });
+ });
+
+ describe('updateContainer', () => {
+ describe('when creating cluster', () => {
+ it('should show the creating container', () => {
+ 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')).toBeFalsy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ });
+ });
+
+ describe('when cluster is created', () => {
+ it('should show the success container and fresh the page', () => {
+ cluster.updateContainer(null, 'created');
+
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(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(null, 'errored', 'this is an error');
+
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(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();
+ });
+ });
+ });
+
+ describe('installApplication', () => {
+ it('tries to install helm', () => {
+ jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
+
+ cluster.installApplication({ id: 'helm' });
+
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
+ expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalledWith('helm', undefined);
+ });
+
+ it('tries to install ingress', () => {
+ jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+
+ expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
+
+ cluster.installApplication({ id: 'ingress' });
+
+ expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUBMITTED);
+ expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalledWith('ingress', undefined);
+ });
+
+ it('tries to install runner', () => {
+ jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+
+ expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
+
+ cluster.installApplication({ id: 'runner' });
+
+ expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUBMITTED);
+ expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalledWith('runner', undefined);
+ });
+
+ it('tries to install jupyter', () => {
+ jest.spyOn(cluster.service, 'installApplication').mockResolvedValueOnce();
+
+ expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
+ cluster.installApplication({
+ id: 'jupyter',
+ params: { hostname: cluster.store.state.applications.jupyter.hostname },
+ });
+
+ expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUBMITTED);
+ expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', {
+ hostname: cluster.store.state.applications.jupyter.hostname,
+ });
+ });
+
+ it('sets error request status when the request fails', () => {
+ jest
+ .spyOn(cluster.service, 'installApplication')
+ .mockRejectedValueOnce(new Error('STUBBED ERROR'));
+
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
+
+ const promise = cluster.installApplication({ id: 'helm' });
+
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
+ expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
+ expect(cluster.service.installApplication).toHaveBeenCalled();
+
+ return promise.then(() => {
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_FAILURE);
+ expect(cluster.store.state.applications.helm.requestReason).toBeDefined();
+ });
+ });
+ });
+
+ describe('handleSuccess', () => {
+ beforeEach(() => {
+ jest.spyOn(cluster.store, 'updateStateFromServer').mockReturnThis();
+ jest.spyOn(cluster, 'toggleIngressDomainHelpText').mockReturnThis();
+ jest.spyOn(cluster, 'checkForNewInstalls').mockReturnThis();
+ jest.spyOn(cluster, 'updateContainer').mockReturnThis();
+
+ cluster.handleSuccess({ data: {} });
+ });
+
+ it('updates clusters store', () => {
+ expect(cluster.store.updateStateFromServer).toHaveBeenCalled();
+ });
+
+ it('checks for new installable apps', () => {
+ expect(cluster.checkForNewInstalls).toHaveBeenCalled();
+ });
+
+ it('toggles ingress domain help text', () => {
+ expect(cluster.toggleIngressDomainHelpText).toHaveBeenCalled();
+ });
+
+ it('updates message containers', () => {
+ expect(cluster.updateContainer).toHaveBeenCalled();
+ });
+ });
+
+ describe('toggleIngressDomainHelpText', () => {
+ const { INSTALLED, INSTALLABLE, NOT_INSTALLABLE } = APPLICATION_STATUS;
+ let ingressPreviousState;
+ let ingressNewState;
+
+ beforeEach(() => {
+ ingressPreviousState = { status: INSTALLABLE };
+ ingressNewState = { status: INSTALLED, externalIp: '127.0.0.1' };
+ });
+
+ describe(`when ingress application new status is ${INSTALLED}`, () => {
+ beforeEach(() => {
+ ingressNewState.status = INSTALLED;
+ cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+ });
+
+ it('displays custom domain help text', () => {
+ expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(false);
+ });
+
+ it('updates ingress external ip address', () => {
+ expect(cluster.ingressDomainSnippet.textContent).toEqual(
+ `${ingressNewState.externalIp}${INGRESS_DOMAIN_SUFFIX}`,
+ );
+ });
+ });
+
+ describe(`when ingress application new status is different from ${INSTALLED}`, () => {
+ it('hides custom domain help text', () => {
+ ingressNewState.status = NOT_INSTALLABLE;
+ cluster.ingressDomainHelpText.classList.remove('hide');
+
+ cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+
+ expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
+ });
+ });
+
+ describe('when ingress application new status and old status are the same', () => {
+ it('does not display custom domain help text', () => {
+ ingressPreviousState.status = INSTALLED;
+ ingressNewState.status = ingressPreviousState.status;
+
+ cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+
+ expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
+ });
+ });
+
+ describe(`when ingress new status is ${INSTALLED} and there isn’t an ip assigned`, () => {
+ it('does not display custom domain help text', () => {
+ ingressNewState.externalIp = null;
+
+ cluster.toggleIngressDomainHelpText(ingressPreviousState, ingressNewState);
+
+ expect(cluster.ingressDomainHelpText.classList.contains('hide')).toEqual(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
new file mode 100644
index 00000000000..b28d0075d06
--- /dev/null
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -0,0 +1,406 @@
+import Vue from 'vue';
+import eventHub from '~/clusters/event_hub';
+import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from '~/clusters/constants';
+import applicationRow from '~/clusters/components/application_row.vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { DEFAULT_APPLICATION_STATE } from '../services/mock_data';
+
+describe('Application Row', () => {
+ let vm;
+ let ApplicationRow;
+
+ beforeEach(() => {
+ ApplicationRow = Vue.extend(applicationRow);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('Title', () => {
+ it('shows title', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ titleLink: null,
+ });
+ const title = vm.$el.querySelector('.js-cluster-application-title');
+
+ expect(title.tagName).toEqual('SPAN');
+ expect(title.textContent.trim()).toEqual(DEFAULT_APPLICATION_STATE.title);
+ });
+
+ it('shows title link', () => {
+ expect(DEFAULT_APPLICATION_STATE.titleLink).toBeDefined();
+
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ });
+ const title = vm.$el.querySelector('.js-cluster-application-title');
+
+ expect(title.tagName).toEqual('A');
+ expect(title.textContent.trim()).toEqual(DEFAULT_APPLICATION_STATE.title);
+ });
+ });
+
+ describe('Install button', () => {
+ it('has indeterminate state on page load', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: null,
+ });
+
+ expect(vm.installButtonLabel).toBeUndefined();
+ });
+
+ it('has install button', () => {
+ const installationBtn = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ expect(installationBtn).not.toBe(null);
+ });
+
+ it('has disabled "Install" when APPLICATION_STATUS.NOT_INSTALLABLE', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.NOT_INSTALLABLE,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Install');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has enabled "Install" when APPLICATION_STATUS.INSTALLABLE', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Install');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(false);
+ });
+
+ it('has loading "Installing" when APPLICATION_STATUS.SCHEDULED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.SCHEDULED,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installing');
+ expect(vm.installButtonLoading).toEqual(true);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has loading "Installing" when APPLICATION_STATUS.INSTALLING', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLING,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installing');
+ expect(vm.installButtonLoading).toEqual(true);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has loading "Installing" when REQUEST_SUBMITTED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ requestStatus: REQUEST_SUBMITTED,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installing');
+ expect(vm.installButtonLoading).toEqual(true);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLED,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installed');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has disabled "Installed" when APPLICATION_STATUS.UPDATING', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installed');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
+ it('has enabled "Install" when APPLICATION_STATUS.ERROR', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.ERROR,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Install');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(false);
+ });
+
+ it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ requestStatus: REQUEST_FAILURE,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Install');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(false);
+ });
+
+ it('clicking install button emits event', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ });
+ const installButton = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ installButton.click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('installApplication', {
+ id: DEFAULT_APPLICATION_STATE.id,
+ params: {},
+ });
+ });
+
+ it('clicking install button when installApplicationRequestParams are provided emits event', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ installApplicationRequestParams: { hostname: 'jupyter' },
+ });
+ const installButton = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ installButton.click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('installApplication', {
+ id: DEFAULT_APPLICATION_STATE.id,
+ params: { hostname: 'jupyter' },
+ });
+ });
+
+ it('clicking disabled install button emits nothing', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLING,
+ });
+ const installButton = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ expect(vm.installButtonDisabled).toEqual(true);
+
+ installButton.click();
+
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('Upgrade button', () => {
+ it('has indeterminate state on page load', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: null,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).toBe(null);
+ });
+
+ it('has enabled "Upgrade" when "upgradeAvailable" is true', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ upgradeAvailable: true,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(upgradeBtn.innerHTML).toContain('Upgrade');
+ });
+
+ it('has enabled "Retry update" when APPLICATION_STATUS.UPDATE_ERRORED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(vm.upgradeFailed).toBe(true);
+ expect(upgradeBtn.innerHTML).toContain('Retry update');
+ });
+
+ it('has disabled "Updating" when APPLICATION_STATUS.UPDATING', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ expect(upgradeBtn).not.toBe(null);
+ expect(vm.isUpgrading).toBe(true);
+ expect(upgradeBtn.innerHTML).toContain('Updating');
+ });
+
+ it('clicking upgrade button emits event', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ upgradeBtn.click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('upgradeApplication', {
+ id: DEFAULT_APPLICATION_STATE.id,
+ params: {},
+ });
+ });
+
+ it('clicking disabled upgrade button emits nothing', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+ const upgradeBtn = vm.$el.querySelector('.js-cluster-application-upgrade-button');
+
+ upgradeBtn.click();
+
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+
+ it('displays an error message if application upgrade failed', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ title: 'GitLab Runner',
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ });
+ const failureMessage = vm.$el.querySelector(
+ '.js-cluster-application-upgrade-failure-message',
+ );
+
+ expect(failureMessage).not.toBe(null);
+ expect(failureMessage.innerHTML).toContain(
+ 'Update failed. Please check the logs and try again.',
+ );
+ });
+ });
+
+ describe('Version', () => {
+ it('displays a version number if application has been upgraded', () => {
+ const version = '0.1.45';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATED,
+ version,
+ });
+ const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(upgradeDetails.innerHTML).toContain('Upgraded');
+ expect(versionEl).not.toBe(null);
+ expect(versionEl.innerHTML).toContain(version);
+ });
+
+ it('contains a link to the chart repo if application has been upgraded', () => {
+ const version = '0.1.45';
+ const chartRepo = 'https://gitlab.com/charts/gitlab-runner';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATED,
+ chartRepo,
+ version,
+ });
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(versionEl.href).toEqual(chartRepo);
+ expect(versionEl.target).toEqual('_blank');
+ });
+
+ it('does not display a version number if application upgrade failed', () => {
+ const version = '0.1.45';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATE_ERRORED,
+ version,
+ });
+ const upgradeDetails = vm.$el.querySelector('.js-cluster-application-upgrade-details');
+ const versionEl = vm.$el.querySelector('.js-cluster-application-upgrade-version');
+
+ expect(upgradeDetails.innerHTML).toContain('failed');
+ expect(versionEl).toBe(null);
+ });
+ });
+
+ describe('Error block', () => {
+ it('does not show error block when there is no error', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: null,
+ requestStatus: null,
+ });
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+
+ expect(generalErrorMessage).toBeNull();
+ });
+
+ it('shows status reason when APPLICATION_STATUS.ERROR', () => {
+ const statusReason = 'We broke it 0.0';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.ERROR,
+ statusReason,
+ });
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+ const statusErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-status-error-message',
+ );
+
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
+ );
+
+ expect(statusErrorMessage.textContent.trim()).toEqual(statusReason);
+ });
+
+ it('shows request reason when REQUEST_FAILURE', () => {
+ const requestReason = 'We broke thre request 0.0';
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ requestStatus: REQUEST_FAILURE,
+ requestReason,
+ });
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+ const requestErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-request-error-message',
+ );
+
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
+ );
+
+ expect(requestErrorMessage.textContent.trim()).toEqual(requestReason);
+ });
+ });
+});
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
new file mode 100644
index 00000000000..7c54a27d950
--- /dev/null
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -0,0 +1,350 @@
+import Vue from 'vue';
+import applications from '~/clusters/components/applications.vue';
+import { CLUSTER_TYPE } from '~/clusters/constants';
+import eventHub from '~/clusters/event_hub';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
+
+describe('Applications', () => {
+ let vm;
+ let Applications;
+
+ beforeEach(() => {
+ Applications = Vue.extend(applications);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('Project cluster applications', () => {
+ beforeEach(() => {
+ vm = mountComponent(Applications, {
+ applications: APPLICATIONS_MOCK_STATE,
+ type: CLUSTER_TYPE.PROJECT,
+ });
+ });
+
+ it('renders a row for Helm Tiller', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-helm')).not.toBeNull();
+ });
+
+ it('renders a row for Ingress', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-ingress')).not.toBeNull();
+ });
+
+ it('renders a row for Cert-Manager', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).not.toBeNull();
+ });
+
+ it('renders a row for Prometheus', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).not.toBeNull();
+ });
+
+ it('renders a row for GitLab Runner', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-runner')).not.toBeNull();
+ });
+
+ it('renders a row for Jupyter', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-jupyter')).not.toBeNull();
+ });
+
+ it('renders a row for Knative', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-knative')).not.toBeNull();
+ });
+ });
+
+ describe('Group cluster applications', () => {
+ beforeEach(() => {
+ vm = mountComponent(Applications, {
+ type: CLUSTER_TYPE.GROUP,
+ applications: APPLICATIONS_MOCK_STATE,
+ });
+ });
+
+ it('renders a row for Helm Tiller', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-helm')).not.toBeNull();
+ });
+
+ it('renders a row for Ingress', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-ingress')).not.toBeNull();
+ });
+
+ it('renders a row for Cert-Manager', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).not.toBeNull();
+ });
+
+ it('renders a row for Prometheus', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).toBeNull();
+ });
+
+ it('renders a row for GitLab Runner', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-runner')).not.toBeNull();
+ });
+
+ it('renders a row for Jupyter', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-jupyter')).toBeNull();
+ });
+
+ it('renders a row for Knative', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-knative')).toBeNull();
+ });
+ });
+
+ describe('Ingress application', () => {
+ describe('when installed', () => {
+ describe('with ip address', () => {
+ it('renders ip address with a clipboard button', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ ingress: {
+ title: 'Ingress',
+ status: 'installed',
+ externalIp: '0.0.0.0',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-endpoint').value).toEqual('0.0.0.0');
+
+ expect(
+ vm.$el.querySelector('.js-clipboard-btn').getAttribute('data-clipboard-text'),
+ ).toEqual('0.0.0.0');
+ });
+ });
+
+ describe('with hostname', () => {
+ it('renders hostname with a clipboard button', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ingress: {
+ title: 'Ingress',
+ status: 'installed',
+ externalHostname: 'localhost.localdomain',
+ },
+ helm: { title: 'Helm Tiller' },
+ cert_manager: { title: 'Cert-Manager' },
+ runner: { title: 'GitLab Runner' },
+ prometheus: { title: 'Prometheus' },
+ jupyter: { title: 'JupyterHub', hostname: '' },
+ knative: { title: 'Knative', hostname: '' },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-endpoint').value).toEqual('localhost.localdomain');
+
+ expect(
+ vm.$el.querySelector('.js-clipboard-btn').getAttribute('data-clipboard-text'),
+ ).toEqual('localhost.localdomain');
+ });
+ });
+
+ describe('without ip address', () => {
+ it('renders an input text with a loading icon and an alert text', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ ingress: {
+ title: 'Ingress',
+ status: 'installed',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-ingress-ip-loading-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.js-no-endpoint-message')).not.toBe(null);
+ });
+ });
+ });
+
+ describe('before installing', () => {
+ it('does not render the IP address', () => {
+ vm = mountComponent(Applications, {
+ applications: APPLICATIONS_MOCK_STATE,
+ });
+
+ expect(vm.$el.textContent).not.toContain('Ingress IP Address');
+ expect(vm.$el.querySelector('.js-endpoint')).toBe(null);
+ });
+ });
+
+ describe('Cert-Manager application', () => {
+ describe('when not installed', () => {
+ it('renders email & allows editing', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ cert_manager: {
+ title: 'Cert-Manager',
+ email: 'before@example.com',
+ status: 'installable',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-email').value).toEqual('before@example.com');
+ expect(vm.$el.querySelector('.js-email').getAttribute('readonly')).toBe(null);
+ });
+ });
+
+ describe('when installed', () => {
+ it('renders email in readonly', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ cert_manager: {
+ title: 'Cert-Manager',
+ email: 'after@example.com',
+ status: 'installed',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-email').value).toEqual('after@example.com');
+ expect(vm.$el.querySelector('.js-email').getAttribute('readonly')).toEqual('readonly');
+ });
+ });
+ });
+
+ describe('Jupyter application', () => {
+ describe('with ingress installed with ip & jupyter installable', () => {
+ it('renders hostname active input', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ ingress: {
+ title: 'Ingress',
+ status: 'installed',
+ externalIp: '1.1.1.1',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-hostname').getAttribute('readonly')).toEqual(null);
+ });
+ });
+
+ describe('with ingress installed without external ip', () => {
+ it('does not render hostname input', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ ingress: { title: 'Ingress', status: 'installed' },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-hostname')).toBe(null);
+ });
+ });
+
+ describe('with ingress & jupyter installed', () => {
+ it('renders readonly input', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
+ jupyter: { title: 'JupyterHub', status: 'installed', hostname: '' },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-hostname').getAttribute('readonly')).toEqual('readonly');
+ });
+ });
+
+ describe('without ingress installed', () => {
+ beforeEach(() => {
+ vm = mountComponent(Applications, {
+ applications: APPLICATIONS_MOCK_STATE,
+ });
+ });
+
+ it('does not render input', () => {
+ expect(vm.$el.querySelector('.js-hostname')).toBe(null);
+ });
+
+ it('renders disabled install button', () => {
+ expect(
+ vm.$el
+ .querySelector(
+ '.js-cluster-application-row-jupyter .js-cluster-application-install-button',
+ )
+ .getAttribute('disabled'),
+ ).toEqual('disabled');
+ });
+ });
+ });
+ });
+
+ describe('Knative application', () => {
+ describe('when installed', () => {
+ describe('with ip address', () => {
+ const props = {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ knative: {
+ title: 'Knative',
+ hostname: 'example.com',
+ status: 'installed',
+ externalIp: '1.1.1.1',
+ },
+ },
+ };
+ it('renders ip address with a clipboard button', () => {
+ vm = mountComponent(Applications, props);
+
+ expect(vm.$el.querySelector('.js-knative-endpoint').value).toEqual('1.1.1.1');
+
+ expect(
+ vm.$el
+ .querySelector('.js-knative-endpoint-clipboard-btn')
+ .getAttribute('data-clipboard-text'),
+ ).toEqual('1.1.1.1');
+ });
+
+ it('renders domain & allows editing', () => {
+ expect(vm.$el.querySelector('.js-knative-domainname').value).toEqual('example.com');
+ expect(vm.$el.querySelector('.js-knative-domainname').getAttribute('readonly')).toBe(
+ null,
+ );
+ });
+
+ it('renders an update/save Knative domain button', () => {
+ expect(vm.$el.querySelector('.js-knative-save-domain-button')).not.toBe(null);
+ });
+
+ it('emits event when clicking Save changes button', () => {
+ jest.spyOn(eventHub, '$emit');
+ vm = mountComponent(Applications, props);
+
+ const saveButton = vm.$el.querySelector('.js-knative-save-domain-button');
+
+ saveButton.click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
+ id: 'knative',
+ params: { hostname: 'example.com' },
+ });
+ });
+ });
+
+ describe('without ip address', () => {
+ it('renders an input text with a loading icon and an alert text', () => {
+ vm = mountComponent(Applications, {
+ applications: {
+ ...APPLICATIONS_MOCK_STATE,
+ knative: {
+ title: 'Knative',
+ hostname: 'example.com',
+ status: 'installed',
+ },
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-knative-ip-loading-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.js-no-knative-endpoint-message')).not.toBe(null);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/clusters/services/mock_data.js b/spec/frontend/clusters/services/mock_data.js
new file mode 100644
index 00000000000..b4d1bb710e0
--- /dev/null
+++ b/spec/frontend/clusters/services/mock_data.js
@@ -0,0 +1,130 @@
+import { APPLICATION_STATUS } from '~/clusters/constants';
+
+const CLUSTERS_MOCK_DATA = {
+ GET: {
+ '/gitlab-org/gitlab-shell/clusters/1/status.json': {
+ data: {
+ status: 'errored',
+ status_reason: 'Failed to request to CloudPlatform.',
+ applications: [
+ {
+ name: 'helm',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: null,
+ },
+ {
+ name: 'ingress',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ external_ip: null,
+ external_hostname: null,
+ },
+ {
+ name: 'runner',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: null,
+ },
+ {
+ name: 'prometheus',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'jupyter',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'knative',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'cert_manager',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ email: 'test@example.com',
+ },
+ ],
+ },
+ },
+ '/gitlab-org/gitlab-shell/clusters/2/status.json': {
+ data: {
+ status: 'errored',
+ status_reason: 'Failed to request to CloudPlatform.',
+ applications: [
+ {
+ name: 'helm',
+ status: APPLICATION_STATUS.INSTALLED,
+ status_reason: null,
+ },
+ {
+ name: 'ingress',
+ status: APPLICATION_STATUS.INSTALLED,
+ status_reason: 'Cannot connect',
+ external_ip: '1.1.1.1',
+ external_hostname: null,
+ },
+ {
+ name: 'runner',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: null,
+ },
+ {
+ name: 'prometheus',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'jupyter',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'knative',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'cert_manager',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ email: 'test@example.com',
+ },
+ ],
+ },
+ },
+ },
+ POST: {
+ '/gitlab-org/gitlab-shell/clusters/1/applications/helm': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/ingress': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/cert_manager': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/runner': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/prometheus': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/jupyter': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/knative': {},
+ },
+};
+
+const DEFAULT_APPLICATION_STATE = {
+ id: 'some-app',
+ title: 'My App',
+ titleLink: 'https://about.gitlab.com/',
+ description: 'Some description about this interesting application!',
+ status: null,
+ statusReason: null,
+ requestStatus: null,
+ requestReason: null,
+};
+
+const APPLICATIONS_MOCK_STATE = {
+ helm: { title: 'Helm Tiller', status: 'installable' },
+ ingress: { title: 'Ingress', status: 'installable' },
+ cert_manager: { title: 'Cert-Manager', status: 'installable' },
+ runner: { title: 'GitLab Runner' },
+ prometheus: { title: 'Prometheus' },
+ jupyter: { title: 'JupyterHub', status: 'installable', hostname: '' },
+ knative: { title: 'Knative ', status: 'installable', hostname: '' },
+};
+
+export { CLUSTERS_MOCK_DATA, DEFAULT_APPLICATION_STATE, APPLICATIONS_MOCK_STATE };
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
new file mode 100644
index 00000000000..161722ec571
--- /dev/null
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -0,0 +1,142 @@
+import ClustersStore from '~/clusters/stores/clusters_store';
+import { APPLICATION_STATUS } from '~/clusters/constants';
+import { CLUSTERS_MOCK_DATA } from '../services/mock_data';
+
+describe('Clusters Store', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new ClustersStore();
+ });
+
+ describe('updateStatus', () => {
+ it('should store new status', () => {
+ expect(store.state.status).toEqual(null);
+
+ const newStatus = 'errored';
+ store.updateStatus(newStatus);
+
+ expect(store.state.status).toEqual(newStatus);
+ });
+ });
+
+ describe('updateStatusReason', () => {
+ it('should store new reason', () => {
+ expect(store.state.statusReason).toEqual(null);
+
+ const newReason = 'Something went wrong!';
+ store.updateStatusReason(newReason);
+
+ expect(store.state.statusReason).toEqual(newReason);
+ });
+ });
+
+ describe('updateAppProperty', () => {
+ it('should store new request status', () => {
+ expect(store.state.applications.helm.requestStatus).toEqual(null);
+
+ const newStatus = APPLICATION_STATUS.INSTALLING;
+ store.updateAppProperty('helm', 'requestStatus', newStatus);
+
+ expect(store.state.applications.helm.requestStatus).toEqual(newStatus);
+ });
+
+ it('should store new request reason', () => {
+ expect(store.state.applications.helm.requestReason).toEqual(null);
+
+ const newReason = 'We broke it.';
+ store.updateAppProperty('helm', 'requestReason', newReason);
+
+ expect(store.state.applications.helm.requestReason).toEqual(newReason);
+ });
+ });
+
+ describe('updateStateFromServer', () => {
+ it('should store new polling data from server', () => {
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/1/status.json'].data;
+ store.updateStateFromServer(mockResponseData);
+
+ expect(store.state).toEqual({
+ helpPath: null,
+ ingressHelpPath: null,
+ status: mockResponseData.status,
+ statusReason: mockResponseData.status_reason,
+ rbac: false,
+ 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,
+ externalIp: null,
+ externalHostname: null,
+ },
+ runner: {
+ title: 'GitLab Runner',
+ status: mockResponseData.applications[2].status,
+ statusReason: mockResponseData.applications[2].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ version: mockResponseData.applications[2].version,
+ upgradeAvailable: mockResponseData.applications[2].update_available,
+ chartRepo: 'https://gitlab.com/charts/gitlab-runner',
+ },
+ prometheus: {
+ title: 'Prometheus',
+ status: mockResponseData.applications[3].status,
+ statusReason: mockResponseData.applications[3].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ },
+ jupyter: {
+ title: 'JupyterHub',
+ status: mockResponseData.applications[4].status,
+ statusReason: mockResponseData.applications[4].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ hostname: '',
+ },
+ knative: {
+ title: 'Knative',
+ status: mockResponseData.applications[5].status,
+ statusReason: mockResponseData.applications[5].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ hostname: null,
+ isEditingHostName: false,
+ externalIp: null,
+ externalHostname: null,
+ },
+ cert_manager: {
+ title: 'Cert-Manager',
+ status: mockResponseData.applications[6].status,
+ statusReason: mockResponseData.applications[6].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ email: mockResponseData.applications[6].email,
+ },
+ },
+ });
+ });
+
+ it('sets default hostname for jupyter when ingress has a ip address', () => {
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
+
+ store.updateStateFromServer(mockResponseData);
+
+ expect(store.state.applications.jupyter.hostname).toEqual(
+ `jupyter.${store.state.applications.ingress.externalIp}.nip.io`,
+ );
+ });
+ });
+});