Commit dee867c1 authored by Mark Florian's avatar Mark Florian

Merge branch '207322-improve-i18n-strings' into 'master'

Improve i18n strings on Kubernetes apps page

See merge request gitlab-org/gitlab!33702
parents ade62c1a c87f1f36
......@@ -82,11 +82,6 @@ export default {
required: false,
default: false,
},
installedVia: {
type: String,
required: false,
default: '',
},
version: {
type: String,
required: false,
......@@ -336,11 +331,7 @@ export default {
>
<span v-else class="js-cluster-application-title">{{ title }}</span>
</strong>
<span
v-if="installedVia"
class="js-cluster-application-installed-via"
v-html="installedVia"
></span>
<slot name="installedVia"></slot>
<div>
<slot name="description"></slot>
</div>
......
<script>
import { escape } from 'lodash';
import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg';
import { GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
......@@ -12,7 +11,6 @@ import knativeLogo from 'images/cluster_app_logos/knative.png';
import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
import elasticStackLogo from 'images/cluster_app_logos/elastic_stack.png';
import fluentdLogo from 'images/cluster_app_logos/fluentd.png';
import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import KnativeDomainEditor from './knative_domain_editor.vue';
......@@ -129,22 +127,6 @@ export default {
cloudRun() {
return this.providerType === PROVIDER_TYPE.GCP && this.preInstalledKnative;
},
installedVia() {
if (this.cloudRun) {
return sprintf(
escape(s__(`ClusterIntegration|installed via %{installed_via}`)),
{
installed_via: `<a href="${
this.cloudRunHelpPath
}" target="_blank" rel="noopener noreferrer">${escape(
s__('ClusterIntegration|Cloud Run'),
)}</a>`,
},
false,
);
}
return null;
},
ingress() {
return this.applications.ingress;
},
......@@ -320,17 +302,17 @@ export default {
</template>
<template v-else>
<div class="bs-callout bs-callout-info">
<strong>
<strong data-testid="ingressCostWarning">
<gl-sprintf
:message="
s__(
'ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.',
'ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}.',
)
"
>
<template #pricingLink>
<template #link="{ content }">
<gl-link href="https://cloud.google.com/compute/pricing#lb" target="_blank">{{
s__('ClusterIntegration|pricing')
content
}}</gl-link>
</template>
</gl-sprintf>
......@@ -357,18 +339,16 @@ export default {
title-link="https://cert-manager.readthedocs.io/en/latest/#"
>
<template #description>
<p>
<p data-testid="certManagerDescription">
<gl-sprintf
:message="
s__(`ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates.
Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates
are valid and up-to-date.`)
"
>
<template #letsEncrypt>
<gl-link href="https://letsencrypt.org/" target="_blank">{{
s__(`ClusterIntegration|Let's Encrypt`)
}}</gl-link>
<template #link="{ content }">
<gl-link href="https://letsencrypt.org/" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
......@@ -388,7 +368,7 @@ export default {
<p class="form-text text-muted">
{{
s__(`ClusterIntegration|Issuers represent a certificate authority.
You must provide an email address for your Issuer. `)
You must provide an email address for your Issuer.`)
}}
<gl-link
href="http://docs.cert-manager.io/en/latest/reference/issuers.html?highlight=email"
......@@ -417,20 +397,22 @@ export default {
title-link="https://prometheus.io/docs/introduction/overview/"
>
<template #description>
<gl-sprintf
:message="
s__(`ClusterIntegration|Prometheus is an open-source monitoring system
with %{gitlabIntegrationLink} to monitor deployed applications.`)
"
>
<template #gitlabIntegrationLink>
<gl-link
href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank"
>{{ s__('ClusterIntegration|Gitlab Integration') }}</gl-link
>
</template>
</gl-sprintf>
<span data-testid="prometheusDescription">
<gl-sprintf
:message="
s__(`ClusterIntegration|Prometheus is an open-source monitoring system
with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications.`)
"
>
<template #link="{ content }">
<gl-link
href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
target="_blank"
>{{ content }}</gl-link
>
</template>
</gl-sprintf>
</span>
</template>
</application-row>
<application-row
......@@ -481,11 +463,11 @@ export default {
title-link="https://crossplane.io"
>
<template #description>
<p>
<p data-testid="crossplaneDescription">
<gl-sprintf
:message="
s__(
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{gitlabIntegrationLink}.
`ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}.
Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`,
)
"
......@@ -493,11 +475,11 @@ export default {
<template #code="{content}">
<code>{{ content }}</code>
</template>
<template #gitlabIntegrationLink>
<template #link="{ content }">
<gl-link
href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
target="_blank"
>{{ s__('ClusterIntegration|Gitlab Integration') }}</gl-link
>{{ content }}</gl-link
>
</template>
</gl-sprintf>
......@@ -584,7 +566,6 @@ export default {
hostname: applications.knative.hostname,
pages_domain_id: applications.knative.pagesDomain && applications.knative.pagesDomain.id,
}"
:installed-via="installedVia"
:uninstallable="applications.knative.uninstallable"
:uninstall-successful="applications.knative.uninstallSuccessful"
:uninstall-failed="applications.knative.uninstallFailed"
......@@ -618,6 +599,17 @@ export default {
@set="setKnativeDomain"
/>
</template>
<template v-if="cloudRun" #installedVia>
<span data-testid="installedVia">
<gl-sprintf
:message="s__('ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}')"
>
<template #link="{ content }">
<gl-link :href="cloudRunHelpPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
</template>
</application-row>
<application-row
id="elastic_stack"
......
......@@ -4741,7 +4741,7 @@ msgstr ""
msgid "ClusterIntegration|Cert-Manager"
msgstr ""
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up-to-date."
msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates are valid and up-to-date."
msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
......@@ -4768,9 +4768,6 @@ msgstr ""
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts. This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
msgstr ""
msgid "ClusterIntegration|Cloud Run"
msgstr ""
msgid "ClusterIntegration|Cluster being created"
msgstr ""
......@@ -4855,7 +4852,7 @@ msgstr ""
msgid "ClusterIntegration|Crossplane"
msgstr ""
msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{gitlabIntegrationLink}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
msgstr ""
msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
......@@ -4939,9 +4936,6 @@ msgstr ""
msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
msgid "ClusterIntegration|Gitlab Integration"
msgstr ""
msgid "ClusterIntegration|Global default"
msgstr ""
......@@ -4987,7 +4981,7 @@ msgstr ""
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}."
msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}."
msgstr ""
msgid "ClusterIntegration|Instance cluster"
......@@ -5002,7 +4996,7 @@ msgstr ""
msgid "ClusterIntegration|Issuer Email"
msgstr ""
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer. "
msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer."
msgstr ""
msgid "ClusterIntegration|Jupyter Hostname"
......@@ -5074,9 +5068,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Loading IAM Roles"
msgstr ""
......@@ -5188,7 +5179,7 @@ msgstr ""
msgid "ClusterIntegration|Prometheus"
msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications."
msgstr ""
msgid "ClusterIntegration|Provider details"
......@@ -5515,15 +5506,12 @@ msgstr ""
msgid "ClusterIntegration|documentation"
msgstr ""
msgid "ClusterIntegration|installed via %{installed_via}"
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|meets the requirements"
msgstr ""
msgid "ClusterIntegration|pricing"
msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Applications Cert-Manager application shows the correct description 1`] = `
<p
data-testid="certManagerDescription"
>
Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by
<a
class="gl-link"
href="https://letsencrypt.org/"
rel="noopener noreferrer"
target="_blank"
>
Let's Encrypt
</a>
and ensure that certificates are valid and up-to-date.
</p>
`;
exports[`Applications Crossplane application shows the correct description 1`] = `
<p
data-testid="crossplaneDescription"
>
Crossplane enables declarative provisioning of managed services from your cloud of choice using
<code>
kubectl
</code>
or
<a
class="gl-link"
href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane"
rel="noopener noreferrer"
target="_blank"
>
GitLab Integration
</a>
. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.
</p>
`;
exports[`Applications Ingress application shows the correct warning message 1`] = `
<strong
data-testid="ingressCostWarning"
>
Installing Ingress may incur additional costs. Learn more about
<a
class="gl-link"
href="https://cloud.google.com/compute/pricing#lb"
rel="noopener noreferrer"
target="_blank"
>
pricing
</a>
.
</strong>
`;
exports[`Applications Knative application shows the correct description 1`] = `
<span
data-testid="installedVia"
>
installed via
<a
class="gl-link"
href=""
rel="noopener"
target="_blank"
>
Cloud Run
</a>
</span>
`;
exports[`Applications Prometheus application shows the correct description 1`] = `
<span
data-testid="prometheusDescription"
>
Prometheus is an open-source monitoring system with
<a
class="gl-link"
href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html"
rel="noopener noreferrer"
target="_blank"
>
GitLab Integration
</a>
to monitor deployed applications.
</span>
`;
import { shallowMount, mount } from '@vue/test-utils';
import Applications from '~/clusters/components/applications.vue';
import { CLUSTER_TYPE } from '~/clusters/constants';
import { CLUSTER_TYPE, PROVIDER_TYPE } from '~/clusters/constants';
import { APPLICATIONS_MOCK_STATE } from '../services/mock_data';
import eventHub from '~/clusters/event_hub';
import ApplicationRow from '~/clusters/components/application_row.vue';
......@@ -30,7 +30,7 @@ describe('Applications', () => {
};
const createShallowApp = options => createApp(options, true);
const findByTestId = id => wrapper.find(`[data-testid="${id}"]`);
afterEach(() => {
wrapper.destroy();
});
......@@ -187,6 +187,11 @@ describe('Applications', () => {
});
describe('Ingress application', () => {
it('shows the correct warning message', () => {
createApp();
expect(findByTestId('ingressCostWarning').element).toMatchSnapshot();
});
describe('with nested component', () => {
const propsData = {
applications: {
......@@ -280,113 +285,125 @@ describe('Applications', () => {
expect(wrapper.find('.js-endpoint').exists()).toBe(false);
});
});
});
describe('Cert-Manager application', () => {
describe('when not installed', () => {
it('renders email & allows editing', () => {
createApp({
applications: {
cert_manager: {
title: 'Cert-Manager',
email: 'before@example.com',
status: 'installable',
},
},
});
describe('Cert-Manager application', () => {
it('shows the correct description', () => {
createApp();
expect(findByTestId('certManagerDescription').element).toMatchSnapshot();
});
expect(wrapper.find('.js-email').element.value).toEqual('before@example.com');
expect(wrapper.find('.js-email').attributes('readonly')).toBe(undefined);
describe('when not installed', () => {
it('renders email & allows editing', () => {
createApp({
applications: {
cert_manager: {
title: 'Cert-Manager',
email: 'before@example.com',
status: 'installable',
},
},
});
expect(wrapper.find('.js-email').element.value).toEqual('before@example.com');
expect(wrapper.find('.js-email').attributes('readonly')).toBe(undefined);
});
});
describe('when installed', () => {
it('renders email in readonly', () => {
createApp({
applications: {
cert_manager: {
title: 'Cert-Manager',
email: 'after@example.com',
status: 'installed',
},
describe('when installed', () => {
it('renders email in readonly', () => {
createApp({
applications: {
cert_manager: {
title: 'Cert-Manager',
email: 'after@example.com',
status: 'installed',
},
});
expect(wrapper.find('.js-email').element.value).toEqual('after@example.com');
expect(wrapper.find('.js-email').attributes('readonly')).toEqual('readonly');
},
});
expect(wrapper.find('.js-email').element.value).toEqual('after@example.com');
expect(wrapper.find('.js-email').attributes('readonly')).toEqual('readonly');
});
});
});
describe('Jupyter application', () => {
describe('with ingress installed with ip & jupyter installable', () => {
it('renders hostname active input', () => {
createApp({
applications: {
ingress: {
title: 'Ingress',
status: 'installed',
externalIp: '1.1.1.1',
},
describe('Jupyter application', () => {
describe('with ingress installed with ip & jupyter installable', () => {
it('renders hostname active input', () => {
createApp({
applications: {
ingress: {
title: 'Ingress',
status: 'installed',
externalIp: '1.1.1.1',
},
});
expect(
wrapper.find('.js-cluster-application-row-jupyter .js-hostname').attributes('readonly'),
).toEqual(undefined);
},
});
});
describe('with ingress installed without external ip', () => {
it('does not render hostname input', () => {
createApp({
applications: {
ingress: { title: 'Ingress', status: 'installed' },
},
});
expect(
wrapper.find('.js-cluster-application-row-jupyter .js-hostname').attributes('readonly'),
).toEqual(undefined);
});
});
expect(wrapper.find('.js-cluster-application-row-jupyter .js-hostname').exists()).toBe(
false,
);
describe('with ingress installed without external ip', () => {
it('does not render hostname input', () => {
createApp({
applications: {
ingress: { title: 'Ingress', status: 'installed' },
},
});
});
describe('with ingress & jupyter installed', () => {
it('renders readonly input', () => {
createApp({
applications: {
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
jupyter: { title: 'JupyterHub', status: 'installed', hostname: '' },
},
});
expect(wrapper.find('.js-cluster-application-row-jupyter .js-hostname').exists()).toBe(
false,
);
});
});
expect(
wrapper.find('.js-cluster-application-row-jupyter .js-hostname').attributes('readonly'),
).toEqual('readonly');
describe('with ingress & jupyter installed', () => {
it('renders readonly input', () => {
createApp({
applications: {
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
jupyter: { title: 'JupyterHub', status: 'installed', hostname: '' },
},
});
expect(
wrapper.find('.js-cluster-application-row-jupyter .js-hostname').attributes('readonly'),
).toEqual('readonly');
});
});
describe('without ingress installed', () => {
beforeEach(() => {
createApp();
});
describe('without ingress installed', () => {
beforeEach(() => {
createApp();
});
it('does not render input', () => {
expect(wrapper.find('.js-cluster-application-row-jupyter .js-hostname').exists()).toBe(
false,
);
});
it('does not render input', () => {
expect(wrapper.find('.js-cluster-application-row-jupyter .js-hostname').exists()).toBe(
false,
);
});
it('renders disabled install button', () => {
expect(
wrapper
.find('.js-cluster-application-row-jupyter .js-cluster-application-install-button')
.attributes('disabled'),
).toEqual('disabled');
});
it('renders disabled install button', () => {
expect(
wrapper
.find('.js-cluster-application-row-jupyter .js-cluster-application-install-button')
.attributes('disabled'),
).toEqual('disabled');
});
});
});
describe('Prometheus application', () => {
it('shows the correct description', () => {
createApp();
expect(findByTestId('prometheusDescription').element).toMatchSnapshot();
});
});
describe('Knative application', () => {
const availableDomain = {
id: 4,
......@@ -414,6 +431,18 @@ describe('Applications', () => {
knativeDomainEditor = wrapper.find(KnativeDomainEditor);
});
it('shows the correct description', async () => {
createApp();
wrapper.setProps({
providerType: PROVIDER_TYPE.GCP,
preInstalledKnative: true,
});
await wrapper.vm.$nextTick();
expect(findByTestId('installedVia').element).toMatchSnapshot();
});
it('emits saveKnativeDomain event when knative domain editor emits save event', () => {
propsData.applications.knative.hostname = availableDomain.domain;
propsData.applications.knative.pagesDomain = availableDomain;
......@@ -475,6 +504,11 @@ describe('Applications', () => {
const crossplane = wrapper.find(CrossplaneProviderStack);
expect(crossplane.exists()).toBe(true);
});
it('shows the correct description', () => {
createApp();
expect(findByTestId('crossplaneDescription').element).toMatchSnapshot();
});
});
describe('Elastic Stack application', () => {
......
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