Commit 2df8eb00 authored by Frédéric Caplette's avatar Frédéric Caplette

Merge branch 'ag-328246-activation-modal-mutation-query' into 'master'

Subscription Activation Modal: Better arrange GraphQL mutation and query

See merge request gitlab-org/gitlab!60577
parents 7fc69431 8b39e171
......@@ -37,10 +37,10 @@ export default {
currentSubscription: {
query: subscriptionQueries.query,
update({ currentLicense }) {
return currentLicense;
return currentLicense || {};
},
skip() {
return !this.canShowSubscriptionDetails;
result({ data }) {
this.hasNewLicense = data?.currentLicense && !this.hasActiveLicense;
},
},
subscriptionHistory: {
......@@ -52,20 +52,27 @@ export default {
},
data() {
return {
canShowSubscriptionDetails: this.hasActiveLicense,
currentSubscription: {},
shouldShowSubscriptionActivationNotification: false,
hasDismissedNotification: false,
hasNewLicense: false,
subscriptionHistory: [],
notification: null,
};
},
methods: {
didDismissSuccessAlert() {
this.shouldShowSubscriptionActivationNotification = false;
computed: {
hasValidSubscriptionData() {
return Boolean(Object.keys(this.currentSubscription).length);
},
canShowSubscriptionDetails() {
return this.hasActiveLicense || this.hasValidSubscriptionData;
},
shouldShowActivationNotification() {
return !this.hasDismissedNotification && this.hasNewLicense && this.hasValidSubscriptionData;
},
handleActivation(hasLicense) {
this.shouldShowSubscriptionActivationNotification = hasLicense;
this.canShowSubscriptionDetails = hasLicense;
},
methods: {
dismissSuccessAlert() {
this.hasDismissedNotification = true;
},
},
};
......@@ -76,12 +83,12 @@ export default {
<h4 data-testid="subscription-main-title">{{ $options.i18n.subscriptionMainTitle }}</h4>
<hr />
<gl-alert
v-if="shouldShowSubscriptionActivationNotification"
v-if="shouldShowActivationNotification"
variant="success"
:title="$options.i18n.subscriptionActivationNotificationText"
class="mb-4"
data-testid="subscription-activation-success-alert"
@dismiss="didDismissSuccessAlert"
@dismiss="dismissSuccessAlert"
/>
<subscription-breakdown
v-if="canShowSubscriptionDetails"
......@@ -93,7 +100,7 @@ export default {
<h3 class="gl-mb-7 gl-mt-6 gl-text-center" data-testid="subscription-activation-title">
{{ $options.i18n.subscriptionActivationTitle }}
</h3>
<cloud-license-subscription-activation-form @subscription-activation="handleActivation" />
<cloud-license-subscription-activation-form />
<div class="row gl-mt-7">
<div class="col-lg-6">
<subscription-trial-card />
......
......@@ -9,6 +9,7 @@ import {
GlLink,
GlSprintf,
} from '@gitlab/ui';
import produce from 'immer';
import { helpPagePath } from '~/helpers/help_page_helper';
import validation from '~/vue_shared/directives/validation';
import {
......@@ -17,19 +18,22 @@ import {
subscriptionQueries,
} from '../constants';
export const SUBSCRIPTION_ACTIVATION_EVENT = 'subscription-activation';
const getLicenseFromData = ({
data: {
gitlabSubscriptionActivate: { license },
},
}) => license;
const getErrorsAsData = ({
data: {
gitlabSubscriptionActivate: { errors },
},
}) => errors;
export const SUBSCRIPTION_ACTIVATION_FAILURE_EVENT = 'subscription-activation-failure';
export const adminLicenseUrl = helpPagePath('/user/admin_area/license');
export default {
i18n: {
title: subscriptionActivationForm.title,
howToActivateSubscription: subscriptionActivationForm.howToActivateSubscription,
activationCode: subscriptionActivationForm.activationCode,
pasteActivationCode: subscriptionActivationForm.pasteActivationCode,
acceptTerms: subscriptionActivationForm.acceptTerms,
activateLabel: subscriptionActivationForm.activateLabel,
fieldRequiredMessage,
},
name: 'CloudLicenseSubscriptionActivationForm',
components: {
GlButton,
......@@ -41,12 +45,22 @@ export default {
GlSprintf,
GlLink,
},
i18n: {
title: subscriptionActivationForm.title,
howToActivateSubscription: subscriptionActivationForm.howToActivateSubscription,
activationCode: subscriptionActivationForm.activationCode,
pasteActivationCode: subscriptionActivationForm.pasteActivationCode,
acceptTerms: subscriptionActivationForm.acceptTerms,
activateLabel: subscriptionActivationForm.activateLabel,
fieldRequiredMessage,
},
links: {
adminLicenseUrl,
},
directives: {
validation: validation(),
},
emits: [SUBSCRIPTION_ACTIVATION_FAILURE_EVENT],
data() {
const form = {
state: false,
......@@ -95,21 +109,23 @@ export default {
activationCode: this.form.fields.activationCode.value,
},
},
})
.then(
({
data: {
gitlabSubscriptionActivate: { errors },
},
}) => {
if (errors.length) {
throw new Error();
}
this.$emit(SUBSCRIPTION_ACTIVATION_EVENT, true);
update: (cache, mutation) => {
const license = getLicenseFromData(mutation);
const { query } = subscriptionQueries;
const data = produce(license, (draftData) => {
draftData.currentLicense = license;
});
cache.writeQuery({ query, data });
},
)
})
.then((res) => {
const errors = getErrorsAsData(res);
if (errors.length) {
throw new Error();
}
})
.catch(() => {
this.$emit(SUBSCRIPTION_ACTIVATION_EVENT, null);
this.$emit(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT, null);
})
.finally(() => {
this.isLoading = false;
......
fragment License on CurrentLicense {
id
type
plan
name
email
company
startsAt
expiresAt
activatedAt
lastSync
usersInLicenseCount
billableUsersCount
maximumUserCount
usersOverLicenseCount
}
#import "../fragments/license.fragment.graphql"
mutation($gitlabSubscriptionActivateInput: GitlabSubscriptionActivateInput!) {
gitlabSubscriptionActivate(input: $gitlabSubscriptionActivateInput) {
errors
license {
id
type
plan
name
email
company
startsAt
expiresAt
activatedAt
lastSync
usersInLicenseCount
billableUsersCount
maximumUserCount
usersOverLicenseCount
...License
}
}
}
#import "../fragments/license.fragment.graphql"
query getCurrentLicense {
currentLicense {
id
type
plan
name
email
company
startsAt
expiresAt
activatedAt
lastSync
usersInLicenseCount
billableUsersCount
maximumUserCount
usersOverLicenseCount
...License
}
}
......@@ -8,7 +8,12 @@ import CloudLicenseShowApp from '../components/app.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
defaultClient: createDefaultClient(
{},
{
assumeImmutableResults: true,
},
),
});
export default () => {
......
......@@ -52,12 +52,10 @@ describe('CloudLicenseApp', () => {
afterEach(() => {
wrapper.destroy();
currentSubscriptionResolver.mockRestore();
subscriptionHistoryResolver.mockRestore();
});
describe('Subscription Activation Form', () => {
beforeEach(() => {
it('shows the main title', () => {
currentSubscriptionResolver = jest
.fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
......@@ -65,21 +63,23 @@ describe('CloudLicenseApp', () => {
.fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]);
});
it('shows the main title', () => {
expect(findSubscriptionMainTitle().text()).toBe(subscriptionMainTitle);
});
describe('without an active license', () => {
beforeEach(() => {
currentSubscriptionResolver = jest
.fn()
.mockResolvedValue({ data: { currentLicense: null } });
subscriptionHistoryResolver = jest
.fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: [] } } });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]);
});
it('shows a title saying there is no active subscription', () => {
expect(findSubscriptionActivationTitle().text()).toBe(subscriptionActivationTitle);
});
it('does not query for the current license', () => {
expect(currentSubscriptionResolver).toHaveBeenCalledTimes(0);
});
it('queries for the current history', () => {
expect(subscriptionHistoryResolver).toHaveBeenCalledTimes(1);
});
......@@ -88,18 +88,23 @@ describe('CloudLicenseApp', () => {
expect(findActivateSubscriptionForm().exists()).toBe(true);
});
it('does not the activation success notification', () => {
it('does not show the activation success notification', () => {
expect(findSubscriptionActivationSuccessAlert().exists()).toBe(false);
});
});
describe('activate the license', () => {
describe('activating the license', () => {
beforeEach(() => {
currentSubscriptionResolver = jest
.fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest
.fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } });
createComponent({ hasActiveLicense: false }, [
currentSubscriptionResolver,
subscriptionHistoryResolver,
]);
findActivateSubscriptionForm().vm.$emit('subscription-activation', true);
});
it('passes the correct data to the subscription breakdown', () => {
......
......@@ -2,7 +2,7 @@ import { GlForm, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import CloudLicenseSubscriptionActivationForm, {
SUBSCRIPTION_ACTIVATION_EVENT,
SUBSCRIPTION_ACTIVATION_FAILURE_EVENT,
} from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import { fieldRequiredMessage, subscriptionQueries } from 'ee/pages/admin/cloud_licenses/constants';
import createMockApollo from 'helpers/mock_apollo_helper';
......@@ -132,10 +132,6 @@ describe('CloudLicenseApp', () => {
},
});
});
it('emits a successful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_EVENT)).toEqual([[true]]);
});
});
describe('when the mutation is not successful but looks like it is', () => {
......@@ -147,10 +143,6 @@ describe('CloudLicenseApp', () => {
findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent());
});
it('emits a successful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_EVENT)).toBeUndefined();
});
it.todo('deals with failures in a meaningful way');
});
......@@ -161,8 +153,8 @@ describe('CloudLicenseApp', () => {
findActivateSubscriptionForm().vm.$emit('submit', createFakeEvent());
});
it('emits a successful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_EVENT)).toBeUndefined();
it('emits a unsuccessful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_FAILURE_EVENT)).toBeUndefined();
});
it.todo('deals with failures in a meaningful way');
......
......@@ -86,9 +86,9 @@ export const activateLicenseMutationResponse = {
gitlabSubscriptionActivate: {
license: {
id: 'gid://gitlab/License/3',
type: 'legacy',
type: 'cloud',
plan: 'ultimate',
name: 'Test license',
name: 'Cloud License',
email: 'user@example.com',
company: 'Example Inc',
startsAt: '2020-01-01',
......
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