Commit 111ae4c1 authored by Savas Vedova's avatar Savas Vedova

Merge branch '225834-add-specific-alert-when-newly-added-license-is-future-dated' into 'master'

Feat(Admin Subscriptions): Add future dated alert

See merge request gitlab-org/gitlab!69874
parents be4538b5 bdeb6ffc
<script> <script>
import { GlAlert, GlButton } from '@gitlab/ui'; import { GlAlert, GlButton } from '@gitlab/ui';
import { isInFuture } from '~/lib/utils/datetime/date_calculation_utility';
import { sprintf } from '~/locale';
import { import {
activateSubscription, activateSubscription,
noActiveSubscription, noActiveSubscription,
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
subscriptionActivationFutureDatedNotificationTitle,
subscriptionActivationFutureDatedNotificationMessage,
subscriptionHistoryQueries, subscriptionHistoryQueries,
subscriptionMainTitle, subscriptionMainTitle,
subscriptionQueries, subscriptionQueries,
exportLicenseUsageBtnText, exportLicenseUsageBtnText,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from '../constants'; } from '../constants';
import SubscriptionActivationCard from './subscription_activation_card.vue'; import SubscriptionActivationCard from './subscription_activation_card.vue';
import SubscriptionBreakdown from './subscription_breakdown.vue'; import SubscriptionBreakdown from './subscription_breakdown.vue';
...@@ -28,7 +33,6 @@ export default { ...@@ -28,7 +33,6 @@ export default {
activateSubscription, activateSubscription,
exportLicenseUsageBtnText, exportLicenseUsageBtnText,
noActiveSubscription, noActiveSubscription,
subscriptionActivationNotificationText,
subscriptionMainTitle, subscriptionMainTitle,
}, },
props: { props: {
...@@ -48,9 +52,6 @@ export default { ...@@ -48,9 +52,6 @@ export default {
update({ currentLicense }) { update({ currentLicense }) {
return currentLicense || {}; return currentLicense || {};
}, },
result({ data }) {
this.hasNewLicense = data?.currentLicense && !this.hasActiveLicense;
},
}, },
subscriptionHistory: { subscriptionHistory: {
query: subscriptionHistoryQueries.query, query: subscriptionHistoryQueries.query,
...@@ -62,10 +63,11 @@ export default { ...@@ -62,10 +63,11 @@ export default {
data() { data() {
return { return {
currentSubscription: {}, currentSubscription: {},
hasDismissedNotification: false, activationNotification: null,
hasNewLicense: false, activationListeners: {
[SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT]: this.displayActivationNotification,
},
subscriptionHistory: [], subscriptionHistory: [],
notification: null,
}; };
}, },
computed: { computed: {
...@@ -75,13 +77,22 @@ export default { ...@@ -75,13 +77,22 @@ export default {
canShowSubscriptionDetails() { canShowSubscriptionDetails() {
return this.hasActiveLicense || this.hasValidSubscriptionData; return this.hasActiveLicense || this.hasValidSubscriptionData;
}, },
shouldShowActivationNotification() {
return !this.hasDismissedNotification && this.hasNewLicense && this.hasValidSubscriptionData;
},
}, },
methods: { methods: {
dismissSuccessAlert() { displayActivationNotification(license) {
this.hasDismissedNotification = true; if (isInFuture(new Date(license.startsAt))) {
this.activationNotification = {
title: subscriptionActivationFutureDatedNotificationTitle,
message: sprintf(subscriptionActivationFutureDatedNotificationMessage, {
date: license.startsAt,
}),
};
} else {
this.activationNotification = { title: subscriptionActivationNotificationText };
}
},
dismissActivationNotification() {
this.activationNotification = null;
}, },
}, },
}; };
...@@ -99,24 +110,27 @@ export default { ...@@ -99,24 +110,27 @@ export default {
</div> </div>
<hr /> <hr />
<gl-alert <gl-alert
v-if="shouldShowActivationNotification" v-if="activationNotification"
variant="success" variant="success"
:title="$options.i18n.subscriptionActivationNotificationText" :title="activationNotification.title"
class="mb-4" class="gl-mb-6"
data-testid="subscription-activation-success-alert" data-testid="subscription-activation-success-alert"
@dismiss="dismissSuccessAlert" @dismiss="dismissActivationNotification"
/> >
{{ activationNotification.message }}
</gl-alert>
<subscription-breakdown <subscription-breakdown
v-if="canShowSubscriptionDetails" v-if="canShowSubscriptionDetails"
:subscription="currentSubscription" :subscription="currentSubscription"
:subscription-list="subscriptionHistory" :subscription-list="subscriptionHistory"
v-on="activationListeners"
/> />
<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.noActiveSubscription }} {{ $options.i18n.noActiveSubscription }}
</h3> </h3>
<subscription-activation-card /> <subscription-activation-card v-on="activationListeners" />
<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> <script>
import { GlCard, GlLink, GlSprintf } from '@gitlab/ui'; import { GlCard, GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import { activateSubscription, howToActivateSubscription, uploadLicenseFile } from '../constants'; import {
activateSubscription,
howToActivateSubscription,
uploadLicenseFile,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from '../constants';
import SubscriptionActivationErrors from './subscription_activation_errors.vue'; import SubscriptionActivationErrors from './subscription_activation_errors.vue';
import SubscriptionActivationForm from './subscription_activation_form.vue'; import SubscriptionActivationForm from './subscription_activation_form.vue';
...@@ -30,12 +36,20 @@ export default { ...@@ -30,12 +36,20 @@ export default {
data() { data() {
return { return {
error: null, error: null,
activationListeners: {
[SUBSCRIPTION_ACTIVATION_FAILURE_EVENT]: this.handleActivationFailure,
[SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT]: this.handleActivationSuccess,
},
}; };
}, },
methods: { methods: {
handleFormActivationFailure(error) { handleActivationFailure(error) {
this.error = error; this.error = error;
}, },
handleActivationSuccess(license) {
// Pass on event to parent listeners
this.$emit(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT, license);
},
}, },
}; };
</script> </script>
...@@ -62,10 +76,7 @@ export default { ...@@ -62,10 +76,7 @@ export default {
</template> </template>
</gl-sprintf> </gl-sprintf>
</p> </p>
<subscription-activation-form <subscription-activation-form class="gl-p-5" v-on="activationListeners" />
class="gl-p-5"
@subscription-activation-failure="handleFormActivationFailure"
/>
<template #footer> <template #footer>
<gl-link <gl-link
v-if="licenseUploadPath" v-if="licenseUploadPath"
......
...@@ -13,13 +13,12 @@ import { ...@@ -13,13 +13,12 @@ import {
activateLabel, activateLabel,
INVALID_CODE_ERROR, INVALID_CODE_ERROR,
INVALID_CODE_ERROR_MESSAGE, INVALID_CODE_ERROR_MESSAGE,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
subscriptionActivationForm, subscriptionActivationForm,
subscriptionQueries, subscriptionQueries,
} from '../constants'; } from '../constants';
import { getErrorsAsData, updateSubscriptionAppCache } from '../graphql/utils'; import { getErrorsAsData, getLicenseFromData, updateSubscriptionAppCache } from '../graphql/utils';
export const SUBSCRIPTION_ACTIVATION_FAILURE_EVENT = 'subscription-activation-failure';
export const SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT = 'subscription-activation-success';
export default { export default {
name: 'SubscriptionActivationForm', name: 'SubscriptionActivationForm',
...@@ -48,7 +47,6 @@ export default { ...@@ -48,7 +47,6 @@ export default {
default: false, default: false,
}, },
}, },
emits: [SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT],
data() { data() {
const form = { const form = {
state: false, state: false,
...@@ -81,6 +79,9 @@ export default { ...@@ -81,6 +79,9 @@ export default {
}, },
}, },
methods: { methods: {
handleError(error) {
this.$emit(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, error.message);
},
submit() { submit() {
if (!this.form.state) { if (!this.form.state) {
this.form.showValidation = true; this.form.showValidation = true;
...@@ -96,21 +97,26 @@ export default { ...@@ -96,21 +97,26 @@ export default {
activationCode: this.form.fields.activationCode.value, activationCode: this.form.fields.activationCode.value,
}, },
}, },
update: this.updateSubscriptionAppCache, update: (cache, res) => {
})
.then((res) => {
const errors = getErrorsAsData(res); const errors = getErrorsAsData(res);
if (errors.length) { if (errors.length) {
const [error] = errors; const [error] = errors;
if (error.includes(INVALID_CODE_ERROR_MESSAGE)) { if (error.includes(INVALID_CODE_ERROR_MESSAGE)) {
throw new Error(INVALID_CODE_ERROR); this.handleError(new Error(INVALID_CODE_ERROR));
return;
} }
throw new Error(error); this.handleError(new Error(error));
return;
}
const license = getLicenseFromData(res);
if (license) {
this.$emit(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT, license);
} }
this.$emit(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT); this.updateSubscriptionAppCache(cache, res);
},
}) })
.catch((error) => { .catch((error) => {
this.$emit(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, error.message); this.handleError(error);
}) })
.finally(() => { .finally(() => {
this.isLoading = false; this.isLoading = false;
......
...@@ -5,6 +5,8 @@ import { ...@@ -5,6 +5,8 @@ import {
activateLabel, activateLabel,
activateSubscription, activateSubscription,
subscriptionActivationInsertCode, subscriptionActivationInsertCode,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from '../constants'; } from '../constants';
import SubscriptionActivationErrors from './subscription_activation_errors.vue'; import SubscriptionActivationErrors from './subscription_activation_errors.vue';
import SubscriptionActivationForm from './subscription_activation_form.vue'; import SubscriptionActivationForm from './subscription_activation_form.vue';
...@@ -39,14 +41,20 @@ export default { ...@@ -39,14 +41,20 @@ export default {
data() { data() {
return { return {
error: null, error: null,
activationListeners: {
[SUBSCRIPTION_ACTIVATION_FAILURE_EVENT]: this.handleActivationFailure,
[SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT]: this.handleActivationSuccess,
},
}; };
}, },
methods: { methods: {
handleActivationFailure(error) { handleActivationFailure(error) {
this.error = error; this.error = error;
}, },
handleActivationSuccess() { handleActivationSuccess(license) {
this.$emit('change', false); this.$emit('change', false);
// Pass on event to parent listeners
this.$emit(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT, license);
}, },
handleChange(event) { handleChange(event) {
this.$emit('change', event); this.$emit('change', event);
...@@ -77,8 +85,7 @@ export default { ...@@ -77,8 +85,7 @@ export default {
<subscription-activation-form <subscription-activation-form
ref="form" ref="form"
:hide-submit-button="true" :hide-submit-button="true"
@subscription-activation-failure="handleActivationFailure" v-on="activationListeners"
@subscription-activation-success="handleActivationSuccess"
/> />
</gl-modal> </gl-modal>
</template> </template>
...@@ -156,6 +156,7 @@ export default { ...@@ -156,6 +156,7 @@ export default {
v-if="hasSubscription" v-if="hasSubscription"
v-model="activationModalVisible" v-model="activationModalVisible"
:modal-id="$options.modal.id" :modal-id="$options.modal.id"
v-on="$listeners"
/> />
<user-callout-dismisser <user-callout-dismisser
v-if="canActivateSubscription" v-if="canActivateSubscription"
......
...@@ -7,6 +7,12 @@ export const subscriptionMainTitle = s__('SuperSonics|Your subscription'); ...@@ -7,6 +7,12 @@ 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 subscriptionActivationFutureDatedNotificationTitle = s__(
'SuperSonics|Your future dated license was successfully added',
);
export const subscriptionActivationFutureDatedNotificationMessage = s__(
'SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details.',
);
export const subscriptionActivationInsertCode = __( export const subscriptionActivationInsertCode = __(
"If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process.", "If you've purchased or renewed your subscription and have an activation code, please enter it below to start the activation process.",
); );
...@@ -117,6 +123,9 @@ export const buySubscriptionCard = { ...@@ -117,6 +123,9 @@ export const buySubscriptionCard = {
buttonLabel: s__('SuperSonics|Buy subscription'), buttonLabel: s__('SuperSonics|Buy subscription'),
}; };
export const SUBSCRIPTION_ACTIVATION_FAILURE_EVENT = 'subscription-activation-failure';
export const SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT = 'subscription-activation-success';
export const INVALID_CODE_ERROR_MESSAGE = 'invalid activation code'; export const INVALID_CODE_ERROR_MESSAGE = 'invalid activation code';
export const CONNECTIVITY_ERROR = 'CONNECTIVITY_ERROR'; export const CONNECTIVITY_ERROR = 'CONNECTIVITY_ERROR';
export const INVALID_CODE_ERROR = 'INVALID_CODE_ERROR'; export const INVALID_CODE_ERROR = 'INVALID_CODE_ERROR';
......
...@@ -132,15 +132,60 @@ RSpec.describe 'Admin views Subscription', :js do ...@@ -132,15 +132,60 @@ RSpec.describe 'Admin views Subscription', :js do
expect(page).not_to have_link('Export license usage file', href: admin_license_usage_export_path(format: :csv)) expect(page).not_to have_link('Export license usage file', href: admin_license_usage_export_path(format: :csv))
end end
context 'when activating a subscription fails' do
before do
stub_request(:post, EE::SUBSCRIPTIONS_GRAPHQL_URL)
.to_return(status: 200, body: {
"data": {
"cloudActivationActivate": {
"errors": ["invalid activation code"],
"license": nil
}
}
}.to_json, headers: { 'Content-Type' => 'application/json' })
page.within(find('#content-body', match: :first)) do
fill_activation_form
end
end
it 'shows an error message' do
expect(page).to have_content('An error occurred while activating your subscription.')
end
end
context 'when activating a future-dated subscription' do
before do
license_to_be_created = create(:license, data: create(:gitlab_license, { starts_at: Date.today + 1.month, cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN }).export)
stub_request(:post, EE::SUBSCRIPTIONS_GRAPHQL_URL)
.to_return(status: 200, body: {
"data": {
"cloudActivationActivate": {
"licenseKey": license_to_be_created.data
}
}
}.to_json, headers: { 'Content-Type' => 'application/json' })
page.within(find('#content-body', match: :first)) do
fill_activation_form
end
end
it 'shows a successful future-dated activation message' do
expect(page).to have_content('Your future dated license was successfully added')
end
end
context 'when activating a new subscription' do context 'when activating a new subscription' do
before do before do
license = create(:license, data: create(:gitlab_license, { cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN }).export) license_to_be_created = create(:license, data: create(:gitlab_license, { starts_at: Date.today, cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN }).export)
stub_request(:post, EE::SUBSCRIPTIONS_GRAPHQL_URL) stub_request(:post, EE::SUBSCRIPTIONS_GRAPHQL_URL)
.to_return(status: 200, body: { .to_return(status: 200, body: {
"data": { "data": {
"cloudActivationActivate": { "cloudActivationActivate": {
"licenseKey": license.data "licenseKey": license_to_be_created.data
} }
} }
}.to_json, headers: { 'Content-Type' => 'application/json' }) }.to_json, headers: { 'Content-Type' => 'application/json' })
......
...@@ -8,10 +8,13 @@ import SubscriptionBreakdown from 'ee/admin/subscriptions/show/components/subscr ...@@ -8,10 +8,13 @@ import SubscriptionBreakdown from 'ee/admin/subscriptions/show/components/subscr
import { import {
noActiveSubscription, noActiveSubscription,
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
subscriptionActivationFutureDatedNotificationTitle,
subscriptionHistoryQueries, subscriptionHistoryQueries,
subscriptionMainTitle, subscriptionMainTitle,
subscriptionQueries, subscriptionQueries,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from 'ee/admin/subscriptions/show/constants'; } from 'ee/admin/subscriptions/show/constants';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license, subscriptionHistory } from '../mock_data'; import { license, subscriptionHistory } from '../mock_data';
...@@ -20,6 +23,9 @@ const localVue = createLocalVue(); ...@@ -20,6 +23,9 @@ const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
describe('SubscriptionManagementApp', () => { describe('SubscriptionManagementApp', () => {
// March 16th, 2020
useFakeDate(2021, 2, 16);
let wrapper; let wrapper;
const findActivateSubscriptionCard = () => wrapper.findComponent(SubscriptionActivationCard); const findActivateSubscriptionCard = () => wrapper.findComponent(SubscriptionActivationCard);
...@@ -99,6 +105,28 @@ describe('SubscriptionManagementApp', () => { ...@@ -99,6 +105,28 @@ describe('SubscriptionManagementApp', () => {
it('does not render the "Export license usage file" link', () => { it('does not render the "Export license usage file" link', () => {
expect(findExportLicenseUsageFileLink().exists()).toBe(false); expect(findExportLicenseUsageFileLink().exists()).toBe(false);
}); });
describe('activating the license', () => {
it('shows the activation success notification', async () => {
await findActivateSubscriptionCard().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
license.ULTIMATE,
);
expect(findSubscriptionActivationSuccessAlert().props('title')).toBe(
subscriptionActivationNotificationText,
);
});
it('shows the future dated activation success notification', async () => {
await findActivateSubscriptionCard().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
license.ULTIMATE_FUTURE_DATED,
);
expect(findSubscriptionActivationSuccessAlert().props('title')).toBe(
subscriptionActivationFutureDatedNotificationTitle,
);
});
});
}); });
describe('activating the license', () => { describe('activating the license', () => {
...@@ -122,11 +150,25 @@ describe('SubscriptionManagementApp', () => { ...@@ -122,11 +150,25 @@ describe('SubscriptionManagementApp', () => {
}); });
}); });
it('shows the activation success notification', () => { it('shows the activation success notification', async () => {
await findSubscriptionBreakdown().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
license.ULTIMATE,
);
expect(findSubscriptionActivationSuccessAlert().props('title')).toBe( expect(findSubscriptionActivationSuccessAlert().props('title')).toBe(
subscriptionActivationNotificationText, subscriptionActivationNotificationText,
); );
}); });
it('shows the future dated activation success notification', async () => {
await findSubscriptionBreakdown().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
license.ULTIMATE_FUTURE_DATED,
);
expect(findSubscriptionActivationSuccessAlert().props('title')).toBe(
subscriptionActivationFutureDatedNotificationTitle,
);
});
}); });
describe('with active license', () => { describe('with active license', () => {
......
...@@ -4,11 +4,15 @@ import SubscriptionActivationCard, { ...@@ -4,11 +4,15 @@ import SubscriptionActivationCard, {
activateSubscriptionUrl, activateSubscriptionUrl,
} from 'ee/admin/subscriptions/show/components/subscription_activation_card.vue'; } from 'ee/admin/subscriptions/show/components/subscription_activation_card.vue';
import SubscriptionActivationErrors from 'ee/admin/subscriptions/show/components/subscription_activation_errors.vue'; import SubscriptionActivationErrors from 'ee/admin/subscriptions/show/components/subscription_activation_errors.vue';
import SubscriptionActivationForm, { import SubscriptionActivationForm from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
import {
CONNECTIVITY_ERROR,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
} from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue'; SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
import { CONNECTIVITY_ERROR, uploadLicenseFile } from 'ee/admin/subscriptions/show/constants'; uploadLicenseFile,
} from 'ee/admin/subscriptions/show/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license } from '../mock_data';
describe('CloudLicenseApp', () => { describe('CloudLicenseApp', () => {
let wrapper; let wrapper;
...@@ -80,6 +84,21 @@ describe('CloudLicenseApp', () => { ...@@ -80,6 +84,21 @@ describe('CloudLicenseApp', () => {
expect(findUploadLink().exists()).toBe(false); expect(findUploadLink().exists()).toBe(false);
}); });
describe('when the forms emits a success', () => {
beforeEach(() => {
createComponent();
findSubscriptionActivationForm().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
license.ULTIMATE,
);
});
it('passes on the event to the parent component', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT).length).toBe(1);
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT)[0]).toEqual([license.ULTIMATE]);
});
});
describe('when the forms emits a connectivity error', () => { describe('when the forms emits a connectivity error', () => {
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
......
import { GlForm, GlFormCheckbox, GlFormInput } from '@gitlab/ui'; import { GlForm, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import SubscriptionActivationForm, { import SubscriptionActivationForm from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
import { import {
CONNECTIVITY_ERROR, CONNECTIVITY_ERROR,
INVALID_CODE_ERROR, INVALID_CODE_ERROR,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
subscriptionQueries, subscriptionQueries,
} from 'ee/admin/subscriptions/show/constants'; } from 'ee/admin/subscriptions/show/constants';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
...@@ -140,7 +139,9 @@ describe('SubscriptionActivationForm', () => { ...@@ -140,7 +139,9 @@ describe('SubscriptionActivationForm', () => {
}); });
it('emits a successful event', () => { it('emits a successful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT)).toEqual([[]]); expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT)).toEqual([
[activateLicenseMutationResponse.SUCCESS.data.gitlabSubscriptionActivate.license],
]);
}); });
it('calls the method to update the cache', () => { it('calls the method to update the cache', () => {
......
import { GlModal } from '@gitlab/ui'; import { GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import SubscriptionActivationErrors from 'ee/admin/subscriptions/show/components/subscription_activation_errors.vue'; import SubscriptionActivationErrors from 'ee/admin/subscriptions/show/components/subscription_activation_errors.vue';
import SubscriptionActivationForm, { import SubscriptionActivationForm from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from 'ee/admin/subscriptions/show/components/subscription_activation_form.vue';
import SubscriptionActivationModal from 'ee/admin/subscriptions/show/components/subscription_activation_modal.vue'; import SubscriptionActivationModal from 'ee/admin/subscriptions/show/components/subscription_activation_modal.vue';
import { import {
activateSubscription, activateSubscription,
CONNECTIVITY_ERROR, CONNECTIVITY_ERROR,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
subscriptionActivationInsertCode, subscriptionActivationInsertCode,
} from 'ee/admin/subscriptions/show/constants'; } from 'ee/admin/subscriptions/show/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { preventDefault } from '../../test_helpers'; import { preventDefault } from '../../test_helpers';
import { activateLicenseMutationResponse } from '../mock_data';
describe('SubscriptionActivationModal', () => { describe('SubscriptionActivationModal', () => {
let wrapper; let wrapper;
...@@ -106,9 +106,15 @@ describe('SubscriptionActivationModal', () => { ...@@ -106,9 +106,15 @@ describe('SubscriptionActivationModal', () => {
it('hides the modal', () => { it('hides the modal', () => {
expect(wrapper.emitted('change')).toBeUndefined(); expect(wrapper.emitted('change')).toBeUndefined();
findSubscriptionActivationForm().vm.$emit(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT); findSubscriptionActivationForm().vm.$emit(
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
activateLicenseMutationResponse.SUCCESS.data.gitlabSubscriptionActivate.license,
);
expect(wrapper.emitted('change')).toEqual([[false]]); expect(wrapper.emitted('change')).toEqual([[false]]);
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT)).toEqual([
[activateLicenseMutationResponse.SUCCESS.data.gitlabSubscriptionActivate.license],
]);
}); });
}); });
......
...@@ -17,6 +17,22 @@ export const license = { ...@@ -17,6 +17,22 @@ export const license = {
usersInLicenseCount: '10', usersInLicenseCount: '10',
usersOverLicenseCount: '0', usersOverLicenseCount: '0',
}, },
ULTIMATE_FUTURE_DATED: {
activatedAt: '2021-03-16',
billableUsersCount: '8',
expiresAt: '2023-03-16',
company: 'ACME Corp',
email: 'user@acmecorp.com',
id: 'gid://gitlab/License/13',
lastSync: '2021-03-16T00:00:00.000',
maximumUserCount: '8',
name: 'Jane Doe',
plan: 'ultimate',
startsAt: '2022-03-16',
type: subscriptionTypes.CLOUD,
usersInLicenseCount: '10',
usersOverLicenseCount: '0',
},
}; };
export const subscriptionHistory = [ export const subscriptionHistory = [
......
...@@ -32837,9 +32837,15 @@ msgstr "" ...@@ -32837,9 +32837,15 @@ msgstr ""
msgid "SuperSonics|You do not have an active subscription" msgid "SuperSonics|You do not have an active subscription"
msgstr "" msgstr ""
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
msgstr ""
msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement." msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "" msgstr ""
msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription" msgid "SuperSonics|Your subscription"
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