Commit 80bab2e0 authored by Savas Vedova's avatar Savas Vedova

Merge branch 'ag-328246-activation-modal-components' into 'master'

Subscription Activation Modal: Generalise Activation Form

See merge request gitlab-org/gitlab!60628
parents 4366b711 8b82777c
<script> <script>
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import { import {
activateSubscription,
noActiveSubscription,
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
subscriptionActivationTitle,
subscriptionHistoryQueries, subscriptionHistoryQueries,
subscriptionMainTitle, subscriptionMainTitle,
subscriptionQueries, subscriptionQueries,
} from '../constants'; } from '../constants';
import CloudLicenseSubscriptionActivationForm from './subscription_activation_form.vue'; import SubscriptionActivationCard from './subscription_activation_card.vue';
import SubscriptionBreakdown from './subscription_breakdown.vue'; import SubscriptionBreakdown from './subscription_breakdown.vue';
import SubscriptionPurchaseCard from './subscription_purchase_card.vue'; import SubscriptionPurchaseCard from './subscription_purchase_card.vue';
import SubscriptionTrialCard from './subscription_trial_card.vue'; import SubscriptionTrialCard from './subscription_trial_card.vue';
...@@ -16,14 +17,15 @@ export default { ...@@ -16,14 +17,15 @@ export default {
name: 'CloudLicenseApp', name: 'CloudLicenseApp',
components: { components: {
GlAlert, GlAlert,
CloudLicenseSubscriptionActivationForm, SubscriptionActivationCard,
SubscriptionBreakdown, SubscriptionBreakdown,
SubscriptionPurchaseCard, SubscriptionPurchaseCard,
SubscriptionTrialCard, SubscriptionTrialCard,
}, },
i18n: { i18n: {
activateSubscription,
noActiveSubscription,
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
subscriptionActivationTitle,
subscriptionMainTitle, subscriptionMainTitle,
}, },
props: { props: {
...@@ -98,9 +100,9 @@ export default { ...@@ -98,9 +100,9 @@ export default {
<div v-else class="row"> <div v-else class="row">
<div class="col-12 col-lg-8 offset-lg-2"> <div class="col-12 col-lg-8 offset-lg-2">
<h3 class="gl-mb-7 gl-mt-6 gl-text-center" data-testid="subscription-activation-title"> <h3 class="gl-mb-7 gl-mt-6 gl-text-center" data-testid="subscription-activation-title">
{{ $options.i18n.subscriptionActivationTitle }} {{ $options.i18n.noActiveSubscription }}
</h3> </h3>
<cloud-license-subscription-activation-form /> <subscription-activation-card />
<div class="row gl-mt-7"> <div class="row gl-mt-7">
<div class="col-lg-6"> <div class="col-lg-6">
<subscription-trial-card /> <subscription-trial-card />
......
<script>
import { GlAlert, GlCard, GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import {
activateSubscription,
CONNECTIVITY_ERROR,
connectivityErrorAlert,
connectivityIssue,
howToActivateSubscription,
} from '../constants';
import SubscriptionActivationForm from './subscription_activation_form.vue';
export const adminLicenseUrl = helpPagePath('/user/admin_area/license');
export const troubleshootingHelpLink = helpPagePath('user/admin_area/license.html#troubleshooting');
export const subscriptionActivationHelpLink = helpPagePath('user/admin_area/license.html');
export default {
name: 'SubscriptionActivationCard',
i18n: {
activateSubscription,
connectivityIssueTitle: connectivityIssue,
connectivityIssueSubtitle: connectivityErrorAlert.subtitle,
connectivityIssueHelpText: connectivityErrorAlert.helpText,
howToActivateSubscription,
},
links: {
adminLicenseUrl,
subscriptionActivationHelpLink,
troubleshootingHelpLink,
},
components: {
GlAlert,
GlCard,
GlLink,
GlSprintf,
SubscriptionActivationForm,
},
data() {
return {
error: null,
};
},
computed: {
hasConnectivityIssue() {
return this.error === CONNECTIVITY_ERROR;
},
},
methods: {
handleFormActivationFailure(error) {
this.error = error;
},
},
};
</script>
<template>
<gl-card body-class="gl-p-0">
<template #header>
<h5 class="gl-my-0 gl-font-weight-bold">
{{ $options.i18n.activateSubscription }}
</h5>
</template>
<div
v-if="hasConnectivityIssue"
class="gl-p-5 gl-border-b-1 gl-border-gray-100 gl-border-b-solid"
>
<gl-alert variant="danger" :title="$options.i18n.connectivityIssueTitle" :dismissible="false">
<gl-sprintf :message="$options.i18n.connectivityIssueSubtitle">
<template #link="{ content }">
<gl-link
:href="$options.links.subscriptionActivationHelpLink"
target="_blank"
class="gl-text-decoration-none!"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
<gl-sprintf :message="$options.i18n.connectivityIssueHelpText">
<template #link="{ content }">
<gl-link
:href="$options.links.troubleshootingHelpLink"
target="_blank"
class="gl-text-decoration-none!"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</div>
<p class="gl-mb-0 gl-px-5 gl-pt-5">
<gl-sprintf :message="$options.i18n.howToActivateSubscription">
<template #link="{ content }">
<gl-link :href="$options.links.adminLicenseUrl" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
<subscription-activation-form
class="gl-p-5"
@subscription-activation-failure="handleFormActivationFailure"
/>
</gl-card>
</template>
<script> <script>
import { import {
GlAlert,
GlButton, GlButton,
GlCard,
GlForm, GlForm,
GlFormCheckbox, GlFormCheckbox,
GlFormGroup, GlFormGroup,
...@@ -11,11 +9,9 @@ import { ...@@ -11,11 +9,9 @@ import {
GlSprintf, GlSprintf,
} from '@gitlab/ui'; } from '@gitlab/ui';
import produce from 'immer'; import produce from 'immer';
import { helpPagePath } from '~/helpers/help_page_helper';
import validation from '~/vue_shared/directives/validation'; import validation from '~/vue_shared/directives/validation';
import { import {
CONNECTIVITY_ERROR, activateLabel,
connectivityErrorAlert,
fieldRequiredMessage, fieldRequiredMessage,
subscriptionActivationForm, subscriptionActivationForm,
subscriptionQueries, subscriptionQueries,
...@@ -34,16 +30,11 @@ const getErrorsAsData = ({ ...@@ -34,16 +30,11 @@ const getErrorsAsData = ({
}) => errors; }) => errors;
export const SUBSCRIPTION_ACTIVATION_FAILURE_EVENT = 'subscription-activation-failure'; export const SUBSCRIPTION_ACTIVATION_FAILURE_EVENT = 'subscription-activation-failure';
export const adminLicenseUrl = helpPagePath('/user/admin_area/license');
export const troubleshootingHelpLink = helpPagePath('user/admin_area/license.html#troubleshooting');
export const subscriptionActivationHelpLink = helpPagePath('user/admin_area/license.html');
export default { export default {
name: 'CloudLicenseSubscriptionActivationForm', name: 'CloudLicenseSubscriptionActivationForm',
components: { components: {
GlAlert,
GlButton, GlButton,
GlCard,
GlForm, GlForm,
GlFormGroup, GlFormGroup,
GlFormInput, GlFormInput,
...@@ -52,23 +43,11 @@ export default { ...@@ -52,23 +43,11 @@ export default {
GlLink, GlLink,
}, },
i18n: { i18n: {
title: subscriptionActivationForm.title,
howToActivateSubscription: subscriptionActivationForm.howToActivateSubscription,
activationCode: subscriptionActivationForm.activationCode,
pasteActivationCode: subscriptionActivationForm.pasteActivationCode,
acceptTerms: subscriptionActivationForm.acceptTerms, acceptTerms: subscriptionActivationForm.acceptTerms,
activateLabel: subscriptionActivationForm.activateLabel, activateLabel,
activationCode: subscriptionActivationForm.activationCode,
fieldRequiredMessage, fieldRequiredMessage,
alert: { pasteActivationCode: subscriptionActivationForm.pasteActivationCode,
title: connectivityErrorAlert.title,
subtitle: connectivityErrorAlert.subtitle,
helpText: connectivityErrorAlert.helpText,
},
},
links: {
adminLicenseUrl,
troubleshootingHelpLink,
subscriptionActivationHelpLink,
}, },
directives: { directives: {
validation: validation(), validation: validation(),
...@@ -93,7 +72,6 @@ export default { ...@@ -93,7 +72,6 @@ export default {
return { return {
form, form,
isLoading: false, isLoading: false,
hasConnectivityIssue: false,
}; };
}, },
computed: { computed: {
...@@ -115,7 +93,6 @@ export default { ...@@ -115,7 +93,6 @@ export default {
} }
this.form.showValidation = false; this.form.showValidation = false;
this.isLoading = true; this.isLoading = true;
this.hasConnectivityIssue = false;
this.$apollo this.$apollo
.mutate({ .mutate({
mutation: subscriptionQueries.mutation, mutation: subscriptionQueries.mutation,
...@@ -139,14 +116,12 @@ export default { ...@@ -139,14 +116,12 @@ export default {
.then((res) => { .then((res) => {
const errors = getErrorsAsData(res); const errors = getErrorsAsData(res);
if (errors.length) { if (errors.length) {
if (errors.find((error) => error === CONNECTIVITY_ERROR)) { const [error] = errors;
this.hasConnectivityIssue = true; throw new Error(error);
}
throw new Error();
} }
}) })
.catch(() => { .catch((error) => {
this.$emit(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, null); this.$emit(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, error.message);
}) })
.finally(() => { .finally(() => {
this.isLoading = false; this.isLoading = false;
...@@ -156,99 +131,56 @@ export default { ...@@ -156,99 +131,56 @@ export default {
}; };
</script> </script>
<template> <template>
<gl-card body-class="gl-p-0"> <gl-form novalidate @submit.prevent="submit">
<template #header> <div class="gl-display-flex gl-flex-wrap">
<h5 class="gl-my-0 gl-font-weight-bold">{{ $options.i18n.title }}</h5> <gl-form-group
</template> class="gl-flex-grow-1"
:invalid-feedback="form.fields.activationCode.feedback"
<div data-testid="form-group-activation-code"
v-if="hasConnectivityIssue" >
class="gl-p-5 gl-border-b-1 gl-border-gray-100 gl-border-b-solid" <label class="gl-w-full" for="activation-code-group">
> {{ $options.i18n.activationCode }}
<gl-alert variant="danger" :title="$options.i18n.alert.title" :dismissible="false"> </label>
<gl-sprintf :message="$options.i18n.alert.subtitle"> <gl-form-input
<template #link="{ content }"> id="activation-code-group"
<gl-link v-model="form.fields.activationCode.value"
:href="$options.links.subscriptionActivationHelpLink" v-validation:[form.showValidation]
target="_blank" :disabled="isLoading"
class="gl-text-decoration-none!" :placeholder="$options.i18n.pasteActivationCode"
>{{ content }}</gl-link :state="form.fields.activationCode.state"
> name="activationCode"
</template> class="gl-mb-4"
</gl-sprintf> required
<gl-sprintf :message="$options.i18n.alert.helpText"> />
<template #link="{ content }"> </gl-form-group>
<gl-link
:href="$options.links.troubleshootingHelpLink"
target="_blank"
class="gl-text-decoration-none!"
>
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</div>
<div class="gl-p-5">
<p>
<gl-sprintf :message="$options.i18n.howToActivateSubscription">
<template #link="{ content }">
<gl-link href="$options.links.adminLicenseUrl" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
<gl-form novalidate @submit.prevent="submit">
<div class="gl-display-flex gl-flex-wrap">
<gl-form-group
class="gl-flex-grow-1"
:invalid-feedback="form.fields.activationCode.feedback"
data-testid="form-group-activation-code"
>
<label class="gl-w-full" for="activation-code-group">
{{ $options.i18n.activationCode }}
</label>
<gl-form-input
id="activation-code-group"
v-model="form.fields.activationCode.value"
v-validation:[form.showValidation]
:disabled="isLoading"
:placeholder="$options.i18n.pasteActivationCode"
:state="form.fields.activationCode.state"
name="activationCode"
class="gl-mb-4"
required
/>
</gl-form-group>
<gl-form-group <gl-form-group
class="gl-mb-0" class="gl-mb-0"
:state="isCheckboxValid" :state="isCheckboxValid"
:invalid-feedback="$options.i18n.fieldRequiredMessage" :invalid-feedback="$options.i18n.fieldRequiredMessage"
data-testid="form-group-terms" data-testid="form-group-terms"
> >
<gl-form-checkbox v-model="form.fields.terms.state" :state="isCheckboxValid"> <gl-form-checkbox v-model="form.fields.terms.state" :state="isCheckboxValid">
<gl-sprintf :message="$options.i18n.acceptTerms"> <gl-sprintf :message="$options.i18n.acceptTerms">
<template #link="{ content }"> <template #link="{ content }">
<gl-link href="https://about.gitlab.com/terms/" target="_blank" <gl-link href="https://about.gitlab.com/terms/" target="_blank"
>{{ content }} >{{ content }}
</gl-link> </gl-link>
</template> </template>
</gl-sprintf> </gl-sprintf>
</gl-form-checkbox> </gl-form-checkbox>
</gl-form-group> </gl-form-group>
<gl-button <gl-button
:loading="isRequestingActivation" :loading="isRequestingActivation"
category="primary" category="primary"
class="gl-mt-6 js-no-auto-disable" class="gl-mt-6 js-no-auto-disable"
data-testid="activate-button" data-testid="activate-button"
type="submit" type="submit"
variant="confirm" variant="confirm"
> >
{{ $options.i18n.activateLabel }} {{ $options.i18n.activateLabel }}
</gl-button> </gl-button>
</div>
</gl-form>
</div> </div>
</gl-card> </gl-form>
</template> </template>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui'; import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { import {
manualSyncFailureText, manualSyncFailureText,
manualSyncFailureTitle, connectivityIssue,
manualSyncSuccessfulTitle, manualSyncSuccessfulTitle,
notificationType, notificationType,
} from '../constants'; } from '../constants';
...@@ -17,7 +17,7 @@ export default { ...@@ -17,7 +17,7 @@ export default {
i18n: { i18n: {
manualSyncSuccessfulTitle, manualSyncSuccessfulTitle,
manualSyncFailureText, manualSyncFailureText,
manualSyncFailureTitle, connectivityIssue,
}, },
components: { components: {
GlAlert, GlAlert,
...@@ -62,7 +62,7 @@ export default { ...@@ -62,7 +62,7 @@ export default {
v-else-if="syncDidFail" v-else-if="syncDidFail"
variant="danger" variant="danger"
:dismissible="false" :dismissible="false"
:title="$options.i18n.manualSyncFailureTitle" :title="$options.i18n.connectivityIssue"
data-testid="sync-failure-alert" data-testid="sync-failure-alert"
> >
<gl-sprintf :message="$options.i18n.manualSyncFailureText"> <gl-sprintf :message="$options.i18n.manualSyncFailureText">
......
...@@ -8,9 +8,16 @@ export const subscriptionMainTitle = s__('SuperSonics|Your subscription'); ...@@ -8,9 +8,16 @@ export const subscriptionMainTitle = s__('SuperSonics|Your subscription');
export const subscriptionActivationNotificationText = s__( export const subscriptionActivationNotificationText = s__(
`SuperSonics|Your subscription was successfully activated. You can see the details below.`, `SuperSonics|Your subscription was successfully activated. You can see the details below.`,
); );
export const subscriptionActivationTitle = s__( export const subscriptionActivationInsertCode = __(
`SuperSonics|You do not have an active subscription`, "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process.",
); );
export const howToActivateSubscription = s__(
'SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}.',
);
export const activateLabel = s__('CloudLicense|Activate');
export const activateSubscription = s__('CloudLicense|Activate subscription');
export const enterActivationCode = s__('CloudLicense|Enter activation code');
export const noActiveSubscription = s__(`SuperSonics|You do not have an active subscription`);
export const subscriptionDetailsHeaderText = s__('SuperSonics|Subscription details'); export const subscriptionDetailsHeaderText = s__('SuperSonics|Subscription details');
export const licensedToHeaderText = s__('SuperSonics|Licensed to'); export const licensedToHeaderText = s__('SuperSonics|Licensed to');
export const manageSubscriptionButtonText = s__('SuperSonics|Manage'); export const manageSubscriptionButtonText = s__('SuperSonics|Manage');
...@@ -54,34 +61,22 @@ export const subscriptionTable = { ...@@ -54,34 +61,22 @@ export const subscriptionTable = {
title: __('Subscription History'), title: __('Subscription History'),
type: s__('SuperSonics|Type'), type: s__('SuperSonics|Type'),
}; };
export const connectivityIssue = s__('SuperSonics|There is a connectivity issue.');
export const manualSyncSuccessfulTitle = s__( export const manualSyncSuccessfulTitle = s__(
'SuperSonics|The subscription details synced successfully.', 'SuperSonics|The subscription details synced successfully.',
); );
export const manualSyncFailureText = s__( export const manualSyncFailureText = s__(
'SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}.', 'SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}.',
); );
export const manualSyncFailureTitle = s__('SuperSonics|There is a connectivity issue.');
export const subscriptionActivationForm = { export const subscriptionActivationForm = {
title: s__('CloudLicense|Activate subscription'),
howToActivateSubscription: s__(
'CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}.',
),
activationCode: s__('CloudLicense|Activation code'), activationCode: s__('CloudLicense|Activation code'),
pasteActivationCode: s__('CloudLicense|Paste your activation code'), pasteActivationCode: s__('CloudLicense|Paste your activation code'),
acceptTerms: s__( acceptTerms: s__(
'CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab.', 'CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab.',
), ),
activateLabel: s__('CloudLicense|Activate'),
}; };
export const userNotifications = {
manualSyncSuccessfulTitle: s__('SuperSonics|The subscription details synced successfully.'),
manualSyncFailureText: s__(
'SuperSonics|You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by %{connectivityHelpLinkStart}troubleshooting the activation code%{connectivityHelpLinkEnd}.',
),
manualSyncFailureTitle: s__('SuperSonics|There is a connectivity issue.'),
};
export const notificationType = { export const notificationType = {
SYNC_FAILURE: 'SYNC_FAILURE', SYNC_FAILURE: 'SYNC_FAILURE',
SYNC_SUCCESS: 'SYNC_SUCCESS', SYNC_SUCCESS: 'SYNC_SUCCESS',
...@@ -118,7 +113,6 @@ export const buySubscriptionCard = { ...@@ -118,7 +113,6 @@ export const buySubscriptionCard = {
export const CONNECTIVITY_ERROR = 'CONNECTIVITY_ERROR'; export const CONNECTIVITY_ERROR = 'CONNECTIVITY_ERROR';
export const connectivityErrorAlert = { export const connectivityErrorAlert = {
title: s__('There is a connectivity issue'),
subtitle: s__( subtitle: s__(
'CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription.', 'CloudLicense|To activate your subscription, connect to GitLab servers through the %{linkStart}Cloud Sync service%{linkEnd}, a hassle-free way to manage your subscription.',
), ),
......
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import CloudLicenseApp from 'ee/pages/admin/cloud_licenses/components/app.vue'; import SubscriptionManagementApp from 'ee/pages/admin/cloud_licenses/components/app.vue';
import SubscriptionActivationForm from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue'; import SubscriptionActivationCard from 'ee/pages/admin/cloud_licenses/components/subscription_activation_card.vue';
import SubscriptionBreakdown from 'ee/pages/admin/cloud_licenses/components/subscription_breakdown.vue'; import SubscriptionBreakdown from 'ee/pages/admin/cloud_licenses/components/subscription_breakdown.vue';
import { import {
noActiveSubscription,
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
subscriptionActivationTitle,
subscriptionHistoryQueries, subscriptionHistoryQueries,
subscriptionMainTitle, subscriptionMainTitle,
subscriptionQueries, subscriptionQueries,
...@@ -17,10 +17,10 @@ import { license, subscriptionHistory } from '../mock_data'; ...@@ -17,10 +17,10 @@ import { license, subscriptionHistory } from '../mock_data';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
describe('CloudLicenseApp', () => { describe('SubscriptionManagementApp', () => {
let wrapper; let wrapper;
const findActivateSubscriptionForm = () => wrapper.findComponent(SubscriptionActivationForm); const findActivateSubscriptionCard = () => wrapper.findComponent(SubscriptionActivationCard);
const findSubscriptionBreakdown = () => wrapper.findComponent(SubscriptionBreakdown); const findSubscriptionBreakdown = () => wrapper.findComponent(SubscriptionBreakdown);
const findSubscriptionActivationTitle = () => const findSubscriptionActivationTitle = () =>
wrapper.findByTestId('subscription-activation-title'); wrapper.findByTestId('subscription-activation-title');
...@@ -40,7 +40,7 @@ describe('CloudLicenseApp', () => { ...@@ -40,7 +40,7 @@ describe('CloudLicenseApp', () => {
const createComponent = (props = {}, resolverMock) => { const createComponent = (props = {}, resolverMock) => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(CloudLicenseApp, { shallowMount(SubscriptionManagementApp, {
localVue, localVue,
apolloProvider: createMockApolloProvider(resolverMock), apolloProvider: createMockApolloProvider(resolverMock),
propsData: { propsData: {
...@@ -77,7 +77,7 @@ describe('CloudLicenseApp', () => { ...@@ -77,7 +77,7 @@ describe('CloudLicenseApp', () => {
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]); createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]);
}); });
it('shows a title saying there is no active subscription', () => { it('shows a title saying there is no active subscription', () => {
expect(findSubscriptionActivationTitle().text()).toBe(subscriptionActivationTitle); expect(findSubscriptionActivationTitle().text()).toBe(noActiveSubscription);
}); });
it('queries for the current history', () => { it('queries for the current history', () => {
...@@ -85,7 +85,7 @@ describe('CloudLicenseApp', () => { ...@@ -85,7 +85,7 @@ describe('CloudLicenseApp', () => {
}); });
it('shows the subscription activation form', () => { it('shows the subscription activation form', () => {
expect(findActivateSubscriptionForm().exists()).toBe(true); expect(findActivateSubscriptionCard().exists()).toBe(true);
}); });
it('does not show the activation success notification', () => { it('does not show the activation success notification', () => {
......
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import SubscriptionActivationCard, {
subscriptionActivationHelpLink,
troubleshootingHelpLink,
} from 'ee/pages/admin/cloud_licenses/components/subscription_activation_card.vue';
import SubscriptionActivationForm, {
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
} from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import { CONNECTIVITY_ERROR } from 'ee/pages/admin/cloud_licenses/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('CloudLicenseApp', () => {
let wrapper;
const findConnectivityErrorAlert = () => wrapper.findComponent(GlAlert);
const findSubscriptionActivationForm = () => wrapper.findComponent(SubscriptionActivationForm);
const createComponent = ({ props = {}, stubs = {} } = {}) => {
wrapper = extendedWrapper(
shallowMount(SubscriptionActivationCard, {
propsData: {
...props,
},
stubs,
}),
);
};
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('shows a form', () => {
expect(findSubscriptionActivationForm().exists()).toBe(true);
});
it('does not show any alert', () => {
expect(findConnectivityErrorAlert().exists()).toBe(false);
});
describe('when the forms emits a connectivity error', () => {
beforeEach(() => {
createComponent({ stubs: { GlSprintf } });
findSubscriptionActivationForm().vm.$emit(
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
CONNECTIVITY_ERROR,
);
});
it('shows an alert component', () => {
expect(findConnectivityErrorAlert().exists()).toBe(true);
});
it('shows some help links', () => {
const alert = findConnectivityErrorAlert();
expect(alert.findAll(GlLink).at(0).attributes('href')).toBe(subscriptionActivationHelpLink);
expect(alert.findAll(GlLink).at(1).attributes('href')).toBe(troubleshootingHelpLink);
});
});
});
import { GlAlert, GlForm, GlFormInput, GlFormCheckbox, GlLink, GlSprintf } from '@gitlab/ui'; import { GlForm, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import CloudLicenseSubscriptionActivationForm, { import SubscriptionActivationForm, {
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
troubleshootingHelpLink,
subscriptionActivationHelpLink,
} from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue'; } from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import { fieldRequiredMessage, subscriptionQueries } from 'ee/pages/admin/cloud_licenses/constants'; import {
CONNECTIVITY_ERROR,
fieldRequiredMessage,
subscriptionQueries,
} from 'ee/pages/admin/cloud_licenses/constants';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component'; import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
...@@ -32,7 +34,6 @@ describe('CloudLicenseApp', () => { ...@@ -32,7 +34,6 @@ describe('CloudLicenseApp', () => {
const findActivationCodeFormGroup = () => wrapper.findByTestId('form-group-activation-code'); const findActivationCodeFormGroup = () => wrapper.findByTestId('form-group-activation-code');
const findActivationCodeInput = () => wrapper.findComponent(GlFormInput); const findActivationCodeInput = () => wrapper.findComponent(GlFormInput);
const findActivateSubscriptionForm = () => wrapper.findComponent(GlForm); const findActivateSubscriptionForm = () => wrapper.findComponent(GlForm);
const findConnectivityErrorAlert = () => wrapper.findComponent(GlAlert);
const GlFormInputStub = stubComponent(GlFormInput, { const GlFormInputStub = stubComponent(GlFormInput, {
template: `<input />`, template: `<input />`,
...@@ -43,9 +44,9 @@ describe('CloudLicenseApp', () => { ...@@ -43,9 +44,9 @@ describe('CloudLicenseApp', () => {
stopPropagation, stopPropagation,
}); });
const createComponentWithApollo = ({ props = {}, mutationMock, stubs = {} } = {}) => { const createComponentWithApollo = ({ props = {}, mutationMock } = {}) => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(CloudLicenseSubscriptionActivationForm, { shallowMount(SubscriptionActivationForm, {
localVue, localVue,
apolloProvider: createMockApolloProvider(mutationMock), apolloProvider: createMockApolloProvider(mutationMock),
propsData: { propsData: {
...@@ -53,7 +54,6 @@ describe('CloudLicenseApp', () => { ...@@ -53,7 +54,6 @@ describe('CloudLicenseApp', () => {
}, },
stubs: { stubs: {
GlFormInput: GlFormInputStub, GlFormInput: GlFormInputStub,
...stubs,
}, },
}), }),
); );
...@@ -137,7 +137,7 @@ describe('CloudLicenseApp', () => { ...@@ -137,7 +137,7 @@ describe('CloudLicenseApp', () => {
}); });
}); });
describe('when the mutation is not successful but looks like it is', () => { describe('when the mutation is not successful', () => {
const mutationMock = jest const mutationMock = jest
.fn() .fn()
.mockResolvedValue(activateLicenseMutationResponse.ERRORS_AS_DATA); .mockResolvedValue(activateLicenseMutationResponse.ERRORS_AS_DATA);
...@@ -146,7 +146,9 @@ describe('CloudLicenseApp', () => { ...@@ -146,7 +146,9 @@ describe('CloudLicenseApp', () => {
findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent()); findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent());
}); });
it.todo('deals with failures in a meaningful way'); it('emits a unsuccessful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT)).toBeUndefined();
});
}); });
describe('when the mutation is not successful with connectivity error', () => { describe('when the mutation is not successful with connectivity error', () => {
...@@ -154,21 +156,20 @@ describe('CloudLicenseApp', () => { ...@@ -154,21 +156,20 @@ describe('CloudLicenseApp', () => {
.fn() .fn()
.mockResolvedValue(activateLicenseMutationResponse.CONNECTIVITY_ERROR); .mockResolvedValue(activateLicenseMutationResponse.CONNECTIVITY_ERROR);
beforeEach(async () => { beforeEach(async () => {
createComponentWithApollo({ mutationMock, stubs: { GlSprintf } }); createComponentWithApollo({ mutationMock });
await findActivationCodeInput().vm.$emit('input', fakeActivationCode); await findActivationCodeInput().vm.$emit('input', fakeActivationCode);
await findAgreementCheckbox().vm.$emit('input', true); await findAgreementCheckbox().vm.$emit('input', true);
findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent()); findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent());
}); });
it('shows alert component guiding the user to resolve the connectivity problem', () => { it('emits an failure event with a connectivity error payload', () => {
const alert = findConnectivityErrorAlert(); expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT)).toEqual([
expect(alert.exists()).toBe(true); [CONNECTIVITY_ERROR],
expect(alert.findAll(GlLink).at(0).attributes('href')).toBe(subscriptionActivationHelpLink); ]);
expect(alert.findAll(GlLink).at(1).attributes('href')).toBe(troubleshootingHelpLink);
}); });
}); });
describe('when the mutation is not successful', () => { describe('when the mutation request fails', () => {
const mutationMock = jest.fn().mockRejectedValue(activateLicenseMutationResponse.FAILURE); const mutationMock = jest.fn().mockRejectedValue(activateLicenseMutationResponse.FAILURE);
beforeEach(() => { beforeEach(() => {
createComponentWithApollo({ mutationMock }); createComponentWithApollo({ mutationMock });
...@@ -178,8 +179,6 @@ describe('CloudLicenseApp', () => { ...@@ -178,8 +179,6 @@ describe('CloudLicenseApp', () => {
it('emits a unsuccessful event', () => { it('emits a unsuccessful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT)).toBeUndefined(); expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT)).toBeUndefined();
}); });
it.todo('deals with failures in a meaningful way');
}); });
}); });
}); });
...@@ -4,7 +4,7 @@ import SubscriptionSyncNotifications, { ...@@ -4,7 +4,7 @@ import SubscriptionSyncNotifications, {
SUCCESS_ALERT_DISMISSED_EVENT, SUCCESS_ALERT_DISMISSED_EVENT,
} from 'ee/pages/admin/cloud_licenses/components/subscription_sync_notifications.vue'; } from 'ee/pages/admin/cloud_licenses/components/subscription_sync_notifications.vue';
import { import {
manualSyncFailureTitle, connectivityIssue,
manualSyncSuccessfulTitle, manualSyncSuccessfulTitle,
notificationType, notificationType,
} from 'ee/pages/admin/cloud_licenses/constants'; } from 'ee/pages/admin/cloud_licenses/constants';
...@@ -69,7 +69,7 @@ describe('Subscription Sync Notifications', () => { ...@@ -69,7 +69,7 @@ describe('Subscription Sync Notifications', () => {
}); });
it('displays an alert with a failure title', () => { it('displays an alert with a failure title', () => {
expect(findFailureAlert().props('title')).toBe(manualSyncFailureTitle); expect(findFailureAlert().props('title')).toBe(connectivityIssue);
}); });
it('displays an alert with a failure message', () => { it('displays an alert with a failure message', () => {
......
...@@ -6689,6 +6689,9 @@ msgstr "" ...@@ -6689,6 +6689,9 @@ msgstr ""
msgid "CloudLicense|Buy subscription" msgid "CloudLicense|Buy subscription"
msgstr "" msgstr ""
msgid "CloudLicense|Enter activation code"
msgstr ""
msgid "CloudLicense|Free trial" msgid "CloudLicense|Free trial"
msgstr "" msgstr ""
...@@ -6698,9 +6701,6 @@ msgstr "" ...@@ -6698,9 +6701,6 @@ msgstr ""
msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab." msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr "" msgstr ""
msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
msgid "CloudLicense|Maximum users" msgid "CloudLicense|Maximum users"
msgstr "" msgstr ""
...@@ -16486,6 +16486,9 @@ msgstr "" ...@@ -16486,6 +16486,9 @@ msgstr ""
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page." msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
msgstr "" msgstr ""
msgid "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process."
msgstr ""
msgid "If your HTTP repository is not publicly accessible, add your credentials." msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "" msgstr ""
...@@ -31070,6 +31073,9 @@ msgstr "" ...@@ -31070,6 +31073,9 @@ msgstr ""
msgid "SuperSonics|Last Sync" msgid "SuperSonics|Last Sync"
msgstr "" msgstr ""
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
msgid "SuperSonics|Licensed to" msgid "SuperSonics|Licensed to"
msgstr "" msgstr ""
...@@ -32267,9 +32273,6 @@ msgstr "" ...@@ -32267,9 +32273,6 @@ msgstr ""
msgid "There are running deployments on the environment. Please retry later." msgid "There are running deployments on the environment. Please retry later."
msgstr "" msgstr ""
msgid "There is a connectivity issue"
msgstr ""
msgid "There is a halted Elasticsearch migration" msgid "There is a halted Elasticsearch migration"
msgstr "" msgstr ""
......
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