Commit ca36bc99 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents 7b73618a a9589cdf
...@@ -353,8 +353,10 @@ export default class Clusters { ...@@ -353,8 +353,10 @@ export default class Clusters {
saveKnativeDomain(data) { saveKnativeDomain(data) {
const appId = data.id; const appId = data.id;
this.store.updateAppProperty(appId, 'status', APPLICATION_STATUS.UPDATING); this.store.updateApplication(appId);
this.service.updateApplication(appId, data.params); this.service.updateApplication(appId, data.params).catch(() => {
this.store.notifyUpdateFailure(appId);
});
} }
setKnativeHostname(data) { setKnativeHostname(data) {
......
...@@ -89,6 +89,10 @@ export default { ...@@ -89,6 +89,10 @@ export default {
type: Boolean, type: Boolean,
required: false, required: false,
}, },
updateable: {
type: Boolean,
default: true,
},
updateSuccessful: { updateSuccessful: {
type: Boolean, type: Boolean,
required: false, required: false,
...@@ -326,36 +330,38 @@ export default { ...@@ -326,36 +330,38 @@ export default {
</ul> </ul>
</div> </div>
<div <div v-if="updateable">
v-if="shouldShowUpgradeDetails" <div
class="form-text text-muted label p-0 js-cluster-application-upgrade-details" v-if="shouldShowUpgradeDetails"
> class="form-text text-muted label p-0 js-cluster-application-upgrade-details"
{{ versionLabel }}
<span v-if="updateSuccessful">to</span>
<gl-link
v-if="updateSuccessful"
:href="chartRepo"
target="_blank"
class="js-cluster-application-upgrade-version"
>chart v{{ version }}</gl-link
> >
</div> {{ versionLabel }}
<span v-if="updateSuccessful">to</span>
<div <gl-link
v-if="updateFailed && !isUpgrading" v-if="updateSuccessful"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message" :href="chartRepo"
> target="_blank"
{{ upgradeFailureDescription }} class="js-cluster-application-upgrade-version"
>chart v{{ version }}</gl-link
>
</div>
<div
v-if="updateFailed && !isUpgrading"
class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-upgrade-failure-message"
>
{{ upgradeFailureDescription }}
</div>
<loading-button
v-if="upgradeAvailable || updateFailed || isUpgrading"
class="btn btn-primary js-cluster-application-upgrade-button mt-2"
:loading="isUpgrading"
:disabled="isUpgrading"
:label="upgradeButtonLabel"
@click="upgradeClicked"
/>
</div> </div>
<loading-button
v-if="upgradeAvailable || updateFailed || isUpgrading"
class="btn btn-primary js-cluster-application-upgrade-button mt-2"
:loading="isUpgrading"
:disabled="isUpgrading"
:label="upgradeButtonLabel"
@click="upgradeClicked"
/>
</div> </div>
<div <div
:class="{ 'section-25': showManageButton, 'section-15': !showManageButton }" :class="{ 'section-25': showManageButton, 'section-15': !showManageButton }"
......
...@@ -15,6 +15,7 @@ import prometheusLogo from 'images/cluster_app_logos/prometheus.png'; ...@@ -15,6 +15,7 @@ import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
import { s__, sprintf } from '../../locale'; import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue'; import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue'; import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import KnativeDomainEditor from './knative_domain_editor.vue';
import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants'; import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
import LoadingButton from '~/vue_shared/components/loading_button.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '~/clusters/event_hub'; import eventHub from '~/clusters/event_hub';
...@@ -25,6 +26,7 @@ export default { ...@@ -25,6 +26,7 @@ export default {
clipboardButton, clipboardButton,
LoadingButton, LoadingButton,
GlLoadingIcon, GlLoadingIcon,
KnativeDomainEditor,
}, },
props: { props: {
type: { type: {
...@@ -154,64 +156,21 @@ export default { ...@@ -154,64 +156,21 @@ export default {
knative() { knative() {
return this.applications.knative; return this.applications.knative;
}, },
knativeInstalled() {
return (
this.knative.status === APPLICATION_STATUS.INSTALLED ||
this.knativeUpgrading ||
this.knativeUpgradeFailed ||
this.knative.status === APPLICATION_STATUS.UPDATED
);
},
knativeUpgrading() {
return (
this.knative.status === APPLICATION_STATUS.UPDATING ||
this.knative.status === APPLICATION_STATUS.SCHEDULED
);
},
knativeUpgradeFailed() {
return this.knative.status === APPLICATION_STATUS.UPDATE_ERRORED;
},
knativeExternalEndpoint() {
return this.knative.externalIp || this.knative.externalHostname;
},
knativeDescription() {
return sprintf(
_.escape(
s__(
`ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}.`,
),
),
{
pricingLink: `<strong><a href="https://cloud.google.com/compute/pricing#lb"
target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|pricing'))}</a></strong>`,
},
false,
);
},
canUpdateKnativeEndpoint() {
return this.knativeExternalEndpoint && !this.knativeUpgradeFailed && !this.knativeUpgrading;
},
knativeHostname: {
get() {
return this.knative.hostname;
},
set(hostname) {
eventHub.$emit('setKnativeHostname', {
id: 'knative',
hostname,
});
},
},
}, },
created() { created() {
this.helmInstallIllustration = helmInstallIllustration; this.helmInstallIllustration = helmInstallIllustration;
}, },
methods: { methods: {
saveKnativeDomain() { saveKnativeDomain(hostname) {
eventHub.$emit('saveKnativeDomain', { eventHub.$emit('saveKnativeDomain', {
id: 'knative', id: 'knative',
params: { hostname: this.knative.hostname }, params: { hostname },
});
},
setKnativeHostname(hostname) {
eventHub.$emit('setKnativeHostname', {
id: 'knative',
hostname,
}); });
}, },
}, },
...@@ -318,9 +277,9 @@ export default { ...@@ -318,9 +277,9 @@ export default {
generated endpoint in order to access generated endpoint in order to access
your application after it has been deployed.`) your application after it has been deployed.`)
}} }}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
__('More information') {{ __('More information') }}
}}</a> </a>
</p> </p>
</div> </div>
...@@ -330,9 +289,9 @@ export default { ...@@ -330,9 +289,9 @@ export default {
the process of being assigned. Please check your Kubernetes the process of being assigned. Please check your Kubernetes
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}} }}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
__('More information') {{ __('More information') }}
}}</a> </a>
</p> </p>
</template> </template>
<template v-if="!ingressInstalled"> <template v-if="!ingressInstalled">
...@@ -361,9 +320,9 @@ export default { ...@@ -361,9 +320,9 @@ export default {
<div slot="description"> <div slot="description">
<p v-html="certManagerDescription"></p> <p v-html="certManagerDescription"></p>
<div class="form-group"> <div class="form-group">
<label for="cert-manager-issuer-email">{{ <label for="cert-manager-issuer-email">
s__('ClusterIntegration|Issuer Email') {{ s__('ClusterIntegration|Issuer Email') }}
}}</label> </label>
<div class="input-group"> <div class="input-group">
<input <input
v-model="applications.cert_manager.email" v-model="applications.cert_manager.email"
...@@ -491,9 +450,9 @@ export default { ...@@ -491,9 +450,9 @@ export default {
s__(`ClusterIntegration|Replace this with your own hostname if you want. s__(`ClusterIntegration|Replace this with your own hostname if you want.
If you do so, point hostname to Ingress IP Address from above.`) If you do so, point hostname to Ingress IP Address from above.`)
}} }}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
__('More information') {{ __('More information') }}
}}</a> </a>
</p> </p>
</div> </div>
</template> </template>
...@@ -514,6 +473,7 @@ export default { ...@@ -514,6 +473,7 @@ export default {
:uninstallable="applications.knative.uninstallable" :uninstallable="applications.knative.uninstallable"
:uninstall-successful="applications.knative.uninstallSuccessful" :uninstall-successful="applications.knative.uninstallSuccessful"
:uninstall-failed="applications.knative.uninstallFailed" :uninstall-failed="applications.knative.uninstallFailed"
:updateable="false"
:disabled="!helmInstalled" :disabled="!helmInstalled"
v-bind="applications.knative" v-bind="applications.knative"
title-link="https://github.com/knative/docs" title-link="https://github.com/knative/docs"
...@@ -525,9 +485,9 @@ export default { ...@@ -525,9 +485,9 @@ export default {
s__(`ClusterIntegration|You must have an RBAC-enabled cluster s__(`ClusterIntegration|You must have an RBAC-enabled cluster
to install Knative.`) to install Knative.`)
}} }}
<a :href="helpPath" target="_blank" rel="noopener noreferrer">{{ <a :href="helpPath" target="_blank" rel="noopener noreferrer">
__('More information') {{ __('More information') }}
}}</a> </a>
</p> </p>
<br /> <br />
</span> </span>
...@@ -540,83 +500,13 @@ export default { ...@@ -540,83 +500,13 @@ export default {
}} }}
</p> </p>
<div class="row"> <knative-domain-editor
<template v-if="knativeInstalled || (helmInstalled && rbac)"> v-if="knative.installed || (helmInstalled && rbac)"
<div :knative="knative"
:class="{ 'col-md-6': knativeInstalled, 'col-12': helmInstalled && rbac }" :ingress-dns-help-path="ingressDnsHelpPath"
class="form-group col-sm-12 mb-0" @save="saveKnativeDomain"
> @set="setKnativeHostname"
<label for="knative-domainname"> />
<strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
</label>
<input
id="knative-domainname"
v-model="knativeHostname"
type="text"
class="form-control js-knative-domainname"
/>
</div>
</template>
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
<strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
</label>
<div v-if="knativeExternalEndpoint" class="input-group">
<input
id="knative-endpoint"
:value="knativeExternalEndpoint"
type="text"
class="form-control js-knative-endpoint"
readonly
/>
<span class="input-group-append">
<clipboard-button
:text="knativeExternalEndpoint"
:title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
class="input-group-text js-knative-endpoint-clipboard-btn"
/>
</span>
</div>
<div v-else class="input-group">
<input type="text" class="form-control js-endpoint" readonly />
<gl-loading-icon
class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
/>
</div>
</div>
<p class="form-text text-muted col-12">
{{
s__(
`ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">{{
__('More information')
}}</a>
</p>
<p
v-if="!knativeExternalEndpoint"
class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
>
{{
s__(`ClusterIntegration|The endpoint is in
the process of being assigned. Please check your Kubernetes
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}}
</p>
<button
v-if="canUpdateKnativeEndpoint"
class="btn btn-success js-knative-save-domain-button mt-3 ml-3"
@click="saveKnativeDomain"
>
{{ s__('ClusterIntegration|Save changes') }}
</button>
</template>
</div>
</div> </div>
</application-row> </application-row>
</div> </div>
......
<script>
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
import { APPLICATION_STATUS } from '~/clusters/constants';
const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
export default {
components: {
LoadingButton,
ClipboardButton,
GlLoadingIcon,
},
props: {
knative: {
type: Object,
required: true,
},
ingressDnsHelpPath: {
type: String,
default: '',
},
},
computed: {
saveButtonDisabled() {
return [UNINSTALLING, UPDATING].includes(this.knative.status);
},
saving() {
return [UPDATING].includes(this.knative.status);
},
saveButtonLabel() {
return this.saving ? this.__('Saving') : this.__('Save changes');
},
knativeInstalled() {
return this.knative.installed;
},
knativeExternalEndpoint() {
return this.knative.externalIp || this.knative.externalHostname;
},
knativeUpdateSuccessful() {
return this.knative.updateSuccessful;
},
knativeHostname: {
get() {
return this.knative.hostname;
},
set(hostname) {
this.$emit('set', hostname);
},
},
},
watch: {
knativeUpdateSuccessful(updateSuccessful) {
if (updateSuccessful) {
this.$toast.show(s__('ClusterIntegration|Knative domain name was updated successfully.'));
}
},
},
};
</script>
<template>
<div class="row">
<div
v-if="knative.updateFailed"
class="bs-callout bs-callout-danger cluster-application-banner col-12 mt-2 mb-2 js-cluster-knative-domain-name-failure-message"
>
{{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
</div>
<template>
<div
:class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
class="form-group col-sm-12 mb-0"
>
<label for="knative-domainname">
<strong>{{ s__('ClusterIntegration|Knative Domain Name:') }}</strong>
</label>
<input
id="knative-domainname"
v-model="knativeHostname"
type="text"
class="form-control js-knative-domainname"
/>
</div>
</template>
<template v-if="knativeInstalled">
<div class="form-group col-sm-12 col-md-6 pl-md-0 mb-0 mt-3 mt-md-0">
<label for="knative-endpoint">
<strong>{{ s__('ClusterIntegration|Knative Endpoint:') }}</strong>
</label>
<div v-if="knativeExternalEndpoint" class="input-group">
<input
id="knative-endpoint"
:value="knativeExternalEndpoint"
type="text"
class="form-control js-knative-endpoint"
readonly
/>
<span class="input-group-append">
<clipboard-button
:text="knativeExternalEndpoint"
:title="s__('ClusterIntegration|Copy Knative Endpoint to clipboard')"
class="input-group-text js-knative-endpoint-clipboard-btn"
/>
</span>
</div>
<div v-else class="input-group">
<input type="text" class="form-control js-endpoint" readonly />
<gl-loading-icon
class="position-absolute align-self-center ml-2 js-knative-ip-loading-icon"
/>
</div>
</div>
<p class="form-text text-muted col-12">
{{
s__(
`ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint.`,
)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
<p
v-if="!knativeExternalEndpoint"
class="settings-message js-no-knative-endpoint-message mt-2 mr-3 mb-0 ml-3"
>
{{
s__(`ClusterIntegration|The endpoint is in
the process of being assigned. Please check your Kubernetes
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}}
</p>
<loading-button
class="btn-success js-knative-save-domain-button mt-3 ml-3"
:loading="saving"
:disabled="saveButtonDisabled"
:label="saveButtonLabel"
@click="$emit('save', knativeHostname)"
/>
</template>
</div>
</template>
...@@ -77,6 +77,8 @@ export default class ClusterStore { ...@@ -77,6 +77,8 @@ export default class ClusterStore {
isEditingHostName: false, isEditingHostName: false,
externalIp: null, externalIp: null,
externalHostname: null, externalHostname: null,
updateSuccessful: false,
updateFailed: false,
}, },
}, },
}; };
......
---
title: Do not display Update app button when saving Knative domain name
merge_request: 28904
author:
type: changed
...@@ -95,6 +95,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -95,6 +95,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
#### Modules, Imports, and Exports #### Modules, Imports, and Exports
1. Use ES module syntax to import modules 1. Use ES module syntax to import modules
```javascript ```javascript
// bad // bad
const SomeClass = require('some_class'); const SomeClass = require('some_class');
...@@ -168,6 +169,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -168,6 +169,7 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
Do not use them anymore and feel free to remove them when refactoring legacy code. Do not use them anymore and feel free to remove them when refactoring legacy code.
1. Avoid adding to the global namespace. 1. Avoid adding to the global namespace.
```javascript ```javascript
// bad // bad
window.MyClass = class { /* ... */ }; window.MyClass = class { /* ... */ };
...@@ -176,7 +178,8 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -176,7 +178,8 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
export default class MyClass { /* ... */ } export default class MyClass { /* ... */ }
``` ```
1. Side effects are forbidden in any script which contains exports 1. Side effects are forbidden in any script which contains export
```javascript ```javascript
// bad // bad
export default class MyClass { /* ... */ } export default class MyClass { /* ... */ }
...@@ -449,6 +452,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -449,6 +452,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
#### Props #### Props
1. Props should be declared as an object 1. Props should be declared as an object
```javascript ```javascript
// bad // bad
props: ['foo'] props: ['foo']
......
...@@ -200,10 +200,9 @@ isn't gated by a License or Plan. ...@@ -200,10 +200,9 @@ isn't gated by a License or Plan.
### Undefined feature flags default to "on" ### Undefined feature flags default to "on"
An important side-effect of the [implicit feature An important side-effect of the [implicit feature flags](#implicit-feature-flags)
flags][#implicit-feature-flags] mentioned above is that unless the feature is mentioned above is that unless the feature is explicitly disabled or limited to a
explicitly disabled or limited to a percentage of users, the feature flag check percentage of users, the feature flag check will default to `true`.
will default to `true`.
As an example, if you were to ship the backend half of a feature behind a flag, As an example, if you were to ship the backend half of a feature behind a flag,
you'd want to explicitly disable that flag until the frontend half is also ready you'd want to explicitly disable that flag until the frontend half is also ready
......
...@@ -2913,9 +2913,6 @@ msgstr "" ...@@ -2913,9 +2913,6 @@ msgstr ""
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}." msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgstr "" msgstr ""
msgid "ClusterIntegration|Installing Knative may incur additional costs. Learn more about %{pricingLink}."
msgstr ""
msgid "ClusterIntegration|Instance cluster" msgid "ClusterIntegration|Instance cluster"
msgstr "" msgstr ""
...@@ -2949,6 +2946,9 @@ msgstr "" ...@@ -2949,6 +2946,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Endpoint:" msgid "ClusterIntegration|Knative Endpoint:"
msgstr "" msgstr ""
msgid "ClusterIntegration|Knative domain name was updated successfully."
msgstr ""
msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center." msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr "" msgstr ""
...@@ -3123,6 +3123,9 @@ msgstr "" ...@@ -3123,6 +3123,9 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while uninstalling %{title}" msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
msgstr "" msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain." msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
msgstr "" msgstr ""
......
import Vue from 'vue'; import Vue from 'vue';
import applications from '~/clusters/components/applications.vue'; import applications from '~/clusters/components/applications.vue';
import { CLUSTER_TYPE } from '~/clusters/constants'; import { CLUSTER_TYPE } from '~/clusters/constants';
import eventHub from '~/clusters/event_hub';
import mountComponent from 'helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import { APPLICATIONS_MOCK_STATE } from '../services/mock_data'; import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
import eventHub from '~/clusters/event_hub';
import { shallowMount } from '@vue/test-utils';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
describe('Applications', () => { describe('Applications', () => {
let vm; let vm;
...@@ -277,73 +279,48 @@ describe('Applications', () => { ...@@ -277,73 +279,48 @@ describe('Applications', () => {
}); });
describe('Knative application', () => { describe('Knative application', () => {
describe('when installed', () => { const propsData = {
describe('with ip address', () => { applications: {
const props = { ...APPLICATIONS_MOCK_STATE,
applications: { knative: {
...APPLICATIONS_MOCK_STATE, title: 'Knative',
knative: { hostname: 'example.com',
title: 'Knative', status: 'installed',
hostname: 'example.com', externalIp: '1.1.1.1',
status: 'installed', installed: true,
externalIp: '1.1.1.1', },
}, },
}, };
}; const newHostname = 'newhostname.com';
it('renders ip address with a clipboard button', () => { let wrapper;
vm = mountComponent(Applications, props); let knativeDomainEditor;
expect(vm.$el.querySelector('.js-knative-endpoint').value).toEqual('1.1.1.1'); beforeEach(() => {
wrapper = shallowMount(Applications, { propsData });
expect( jest.spyOn(eventHub, '$emit');
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', () => { knativeDomainEditor = wrapper.find(KnativeDomainEditor);
jest.spyOn(eventHub, '$emit'); });
vm = mountComponent(Applications, props);
const saveButton = vm.$el.querySelector('.js-knative-save-domain-button'); afterEach(() => {
wrapper.destroy();
});
saveButton.click(); it('emits saveKnativeDomain event when knative domain editor emits save event', () => {
knativeDomainEditor.vm.$emit('save', newHostname);
expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', { expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
id: 'knative', id: 'knative',
params: { hostname: 'example.com' }, params: { hostname: newHostname },
});
});
}); });
});
describe('without ip address', () => { it('emits setKnativeHostname event when knative domain editor emits change event', () => {
it('renders an input text with a loading icon and an alert text', () => { wrapper.find(KnativeDomainEditor).vm.$emit('set', newHostname);
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(eventHub.$emit).toHaveBeenCalledWith('setKnativeHostname', {
expect(vm.$el.querySelector('.js-no-knative-endpoint-message')).not.toBe(null); id: 'knative',
}); hostname: newHostname,
}); });
}); });
}); });
......
import { shallowMount } from '@vue/test-utils';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
const { UPDATING } = APPLICATION_STATUS;
describe('KnativeDomainEditor', () => {
let wrapper;
let knative;
const createComponent = (props = {}) => {
wrapper = shallowMount(KnativeDomainEditor, {
propsData: { ...props },
});
};
beforeEach(() => {
knative = {
title: 'Knative',
hostname: 'example.com',
installed: true,
};
});
afterEach(() => {
wrapper.destroy();
});
describe('knative has an assigned IP address', () => {
beforeEach(() => {
knative.externalIp = '1.1.1.1';
createComponent({ knative });
});
it('renders ip address with a clipboard button', () => {
expect(wrapper.find('.js-knative-endpoint').exists()).toBe(true);
expect(wrapper.find('.js-knative-endpoint').element.value).toEqual(knative.externalIp);
});
it('displays ip address clipboard button', () => {
expect(wrapper.find('.js-knative-endpoint-clipboard-btn').attributes('text')).toEqual(
knative.externalIp,
);
});
it('renders domain & allows editing', () => {
const domainNameInput = wrapper.find('.js-knative-domainname');
expect(domainNameInput.element.value).toEqual(knative.hostname);
expect(domainNameInput.attributes('readonly')).toBeFalsy();
});
it('renders an update/save Knative domain button', () => {
expect(wrapper.find('.js-knative-save-domain-button').exists()).toBe(true);
});
});
describe('knative without ip address', () => {
beforeEach(() => {
knative.externalIp = null;
createComponent({ knative });
});
it('renders an input text with a loading icon', () => {
expect(wrapper.find('.js-knative-ip-loading-icon').exists()).toBe(true);
});
it('renders message indicating there is not IP address assigned', () => {
expect(wrapper.find('.js-no-knative-endpoint-message').exists()).toBe(true);
});
});
describe('clicking save changes button', () => {
beforeEach(() => {
createComponent({ knative });
});
it('triggers save event and pass current knative hostname', () => {
wrapper.find(LoadingButton).vm.$emit('click');
expect(wrapper.emitted('save')[0]).toEqual([knative.hostname]);
});
});
describe('when knative domain name was saved successfully', () => {
beforeEach(() => {
createComponent({ knative });
});
it('displays toast indicating a successful update', () => {
wrapper.vm.$toast = { show: jest.fn() };
wrapper.setProps({ knative: Object.assign({ updateSuccessful: true }, knative) });
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
'Knative domain name was updated successfully.',
);
});
});
});
describe('when knative domain name input changes', () => {
it('emits "set" event with updated domain name', () => {
const newHostname = 'newhostname.com';
wrapper.setData({ knativeHostname: newHostname });
expect(wrapper.emitted('set')[0]).toEqual([newHostname]);
});
});
describe('when updating knative domain name failed', () => {
beforeEach(() => {
createComponent({ knative });
});
it('displays an error banner indicating the operation failure', () => {
wrapper.setProps({ knative: { updateFailed: true, ...knative } });
expect(wrapper.find('.js-cluster-knative-domain-name-failure-message').exists()).toBe(true);
});
});
describe(`when knative status is ${UPDATING}`, () => {
beforeEach(() => {
createComponent({ knative: { status: UPDATING, ...knative } });
});
it('renders loading spinner in save button', () => {
expect(wrapper.find(LoadingButton).props('loading')).toBe(true);
});
it('renders disabled save button', () => {
expect(wrapper.find(LoadingButton).props('disabled')).toBe(true);
});
it('renders save button with "Saving" label', () => {
expect(wrapper.find(LoadingButton).props('label')).toBe('Saving');
});
});
});
...@@ -133,6 +133,8 @@ describe('Clusters Store', () => { ...@@ -133,6 +133,8 @@ describe('Clusters Store', () => {
uninstallable: false, uninstallable: false,
uninstallSuccessful: false, uninstallSuccessful: false,
uninstallFailed: false, uninstallFailed: false,
updateSuccessful: false,
updateFailed: false,
}, },
cert_manager: { cert_manager: {
title: 'Cert-Manager', title: 'Cert-Manager',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment