Commit b553f90f authored by Savas Vedova's avatar Savas Vedova

Merge branch 'ag-273028-subs-details-graphql' into 'master'

Subscription Details: integrate GraphQL

See merge request gitlab-org/gitlab!58943
parents 42ece464 73f4067a
<script>
import { s__, sprintf } from '~/locale';
import {
subscriptionActivationTitle,
subscriptionHistoryQueries,
subscriptionMainTitle,
subscriptionQueries,
} from '../constants';
import CloudLicenseSubscriptionActivationForm from './subscription_activation_form.vue';
import SubscriptionBreakdown from './subscription_breakdown.vue';
export default {
name: 'CloudLicenseApp',
components: {
SubscriptionBreakdown,
CloudLicenseSubscriptionActivationForm,
},
i18n: {
mainTitle: s__(`CloudLicense|This instance is currently using the %{planName} plan.`),
subscriptionActivationTitle,
subscriptionMainTitle,
},
inject: ['planName'],
props: {
subscription: {
hasActiveLicense: {
type: Boolean,
required: false,
type: Object,
default: null,
default: false,
},
},
apollo: {
currentSubscription: {
query: subscriptionQueries.query,
update({ currentLicense }) {
return currentLicense;
},
skip() {
return !this.hasCurrentLicense;
},
},
subscriptionHistory: {
query: subscriptionHistoryQueries.query,
update({ licenseHistoryEntries }) {
return licenseHistoryEntries.nodes || [];
},
},
},
data() {
return {
subscriptionData: this.subscription,
currentSubscription: {},
subscriptionHistory: [],
hasCurrentLicense: this.hasActiveLicense,
};
},
computed: {
mainTitle() {
return sprintf(this.$options.i18n.mainTitle, {
planName: this.planName,
});
methods: {
handleActivation(result) {
this.hasCurrentLicense = result;
},
},
};
......@@ -35,13 +59,20 @@ export default {
<template>
<div class="gl-display-flex gl-justify-content-center gl-flex-direction-column">
<h4>{{ s__('CloudLicense|Your subscription') }}</h4>
<h4 data-testid="subscription-main-title">{{ $options.i18n.subscriptionMainTitle }}</h4>
<hr />
<div class="row">
<div v-if="!hasCurrentLicense" class="row">
<div class="col-12 col-lg-8 offset-lg-2">
<h3 class="gl-mb-7 gl-mt-6 gl-text-center">{{ mainTitle }}</h3>
<cloud-license-subscription-activation-form v-if="!subscriptionData" />
<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" />
</div>
</div>
<subscription-breakdown
v-else
:subscription="currentSubscription"
:subscription-list="subscriptionHistory"
/>
</div>
</template>
......@@ -9,7 +9,7 @@ import {
GlLink,
GlSprintf,
} from '@gitlab/ui';
import activateSubscriptionMutation from 'ee/pages/admin/cloud_licenses/graphql/mutations/activate_subscription.mutation.graphql';
import { subscriptionQueries } from '../constants';
export const SUBSCRIPTION_ACTIVATION_EVENT = 'subscription-activation';
......@@ -42,7 +42,7 @@ export default {
this.isLoading = true;
this.$apollo
.mutate({
mutation: activateSubscriptionMutation,
mutation: subscriptionQueries.mutation,
variables: {
gitlabSubscriptionActivateInput: {
activationCode: this.activationCode,
......@@ -58,7 +58,7 @@ export default {
if (errors.length) {
throw new Error();
}
this.$emit(SUBSCRIPTION_ACTIVATION_EVENT, this.activationCode);
this.$emit(SUBSCRIPTION_ACTIVATION_EVENT, true);
},
)
.catch(() => {
......@@ -112,9 +112,9 @@ export default {
"
>
<template #link="{ content }">
<gl-link href="https://about.gitlab.com/terms/" target="_blank">{{
content
}}</gl-link>
<gl-link href="https://about.gitlab.com/terms/" target="_blank"
>{{ content }}
</gl-link>
</template>
</gl-sprintf>
</gl-form-checkbox>
......
......@@ -10,7 +10,7 @@ import SubscriptionDetailsCard from './subscription_details_card.vue';
import SubscriptionDetailsHistory from './subscription_details_history.vue';
import SubscriptionDetailsUserInfo from './subscription_details_user_info.vue';
export const subscriptionDetailsFields = ['id', 'plan', 'lastSync', 'startsAt', 'renews'];
export const subscriptionDetailsFields = ['id', 'plan', 'expiresAt', 'lastSync', 'startsAt'];
export const licensedToFields = ['name', 'email', 'company'];
export default {
......@@ -44,14 +44,17 @@ export default {
};
},
computed: {
canMangeSubscription() {
return false;
},
hasSubscription() {
return Boolean(Object.keys(this.subscription).length);
},
hasSubscriptionHistory() {
return Boolean(this.subscriptionList.length);
},
canMangeSubscription() {
return false;
subscriptionHistory() {
return this.hasSubscriptionHistory ? this.subscriptionList : [this.subscription];
},
},
};
......@@ -87,9 +90,9 @@ export default {
</section>
<subscription-details-user-info v-if="hasSubscription" :subscription="subscription" />
<subscription-details-history
v-if="hasSubscriptionHistory"
v-if="hasSubscription"
:current-subscription-id="subscription.id"
:subscription-list="subscriptionList"
:subscription-list="subscriptionHistory"
/>
</div>
</template>
<script>
import { GlCard } from '@gitlab/ui';
import { identity } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { detailsLabels } from '../constants';
import SubscriptionDetailsTable from './subscription_details_table.vue';
const humanReadableDate = (value) => (value ? formatDate(value, 'd mmmm yyyy') : '');
const subscriptionDetailsFormatRules = {
id: getIdFromGraphQLId,
expiresAt: getTimeago().format,
lastSync: getTimeago().format,
plan: capitalizeFirstCharacter,
startsAt: humanReadableDate,
};
export default {
name: 'SubscriptionDetailsCard',
components: {
......@@ -26,11 +40,13 @@ export default {
},
computed: {
details() {
return this.detailsFields.map((detail) => ({
canCopy: detail === 'id',
label: detailsLabels[detail],
value: this.subscription[detail],
}));
return this.detailsFields.map((detail) => {
const label = detailsLabels[detail];
const formatter = subscriptionDetailsFormatRules[detail] || identity;
const valueToFormat = this.subscription[detail];
const value = valueToFormat ? formatter(valueToFormat) : '';
return { canCopy: detail === 'id', label, value };
});
},
},
};
......
......@@ -59,21 +59,22 @@ export default {
},
{
key: 'plan',
formatter: (v, k, item) => capitalizeFirstCharacter(item.plan),
label: detailsLabels.plan,
tdAttr,
tdClass: this.cellClass,
thClass,
},
{
key: 'startsAt',
label: subscriptionTable.activatedOn,
key: 'activatedAt',
label: subscriptionTable.activatedAt,
tdAttr,
tdClass: this.cellClass,
thClass,
},
{
key: 'validFrom',
label: subscriptionTable.validFrom,
key: 'startsAt',
label: subscriptionTable.startsAt,
tdAttr,
tdClass: this.cellClass,
thClass,
......@@ -86,7 +87,7 @@ export default {
thClass,
},
{
key: 'usersInLicense',
key: 'usersInLicenseCount',
label: subscriptionTable.seats,
tdAttr,
tdClass: this.cellClass,
......@@ -94,6 +95,8 @@ export default {
},
{
key: 'type',
formatter: (v, k, item) =>
sprintf(subscriptionTypeText, { type: capitalizeFirstCharacter(item.type) }),
label: subscriptionTable.type,
tdAttr,
tdClass: this.cellClass,
......@@ -106,9 +109,6 @@ export default {
cellClass(_, x, item) {
return item.id === this.currentSubscriptionId ? tdClassHighlight : tdClassBase;
},
getType(type) {
return sprintf(subscriptionTypeText, { type: capitalizeFirstCharacter(type) });
},
rowAttr() {
return {
'data-testid': 'subscription-history-row',
......@@ -135,8 +135,8 @@ export default {
responsive
stacked="sm"
>
<template #cell(type)="{ item }">
<gl-badge size="md" variant="info">{{ getType(item.type) }}</gl-badge>
<template #cell(type)="{ value }">
<gl-badge size="md" variant="info">{{ value }}</gl-badge>
</template>
</gl-table>
</section>
......
......@@ -21,6 +21,7 @@ export default {
},
{
key: 'value',
formatter: (v, k, item) => item.value.toString(),
label: '',
thClass: DEFAULT_TH_CLASSES,
tdClass: DEFAULT_TD_CLASSES,
......@@ -71,12 +72,12 @@ export default {
</p>
</template>
<template #cell(value)="{ item }">
<template #cell(value)="{ item, value }">
<p class="gl-relative" data-testid="details-content">
{{ item.value }}
{{ value || '-' }}
<clipboard-button
v-if="item.canCopy"
:text="item.value"
:text="value"
:title="$options.i18n.copySubscriptionIdButtonText"
category="tertiary"
class="gl-absolute gl-mt-n2 gl-ml-2"
......
......@@ -12,7 +12,7 @@ import {
usersOverSubscriptionTitle,
} from '../constants';
export const billableUsersURL = helpPagePath('subscriptions/self_managed/index');
export const billableUsersURL = helpPagePath('licenses/self_managed/index');
export const trueUpURL = 'https://about.gitlab.com/license-faq/';
export default {
......@@ -44,16 +44,16 @@ export default {
},
computed: {
usersInSubscription() {
return this.subscription.usersInLicense;
return this.subscription.usersInLicenseCount;
},
billableUsers() {
return this.subscription.billableUsers;
return this.subscription.billableUsersCount;
},
maximumUsers() {
return this.subscription.maximumUsers;
return this.subscription.maximumUserCount;
},
usersOverSubscription() {
return this.subscription.usersOverSubscription;
return this.subscription.usersOverLicenseCount;
},
},
};
......@@ -110,7 +110,7 @@ export default {
</div>
<div class="col-md-6 gl-mb-5">
<gl-card data-testid="users-over-subscription">
<gl-card data-testid="users-over-license">
<header>
<h2>{{ usersOverSubscription }}</h2>
<h5 class="gl-font-weight-normal text-uppercase">
......
import { __, s__ } from '~/locale';
import activateSubscriptionMutation from './graphql/mutations/activate_subscription.mutation.graphql';
import getCurrentLicense from './graphql/queries/get_current_license.query.graphql';
import getLicenseHistory from './graphql/queries/get_license_history.query.graphql';
export const subscriptionMainTitle = s__('SuperSonics|Your subscription');
export const subscriptionActivationTitle = s__(
`SuperSonics|You do not have an active subscription`,
);
export const subscriptionDetailsHeaderText = s__('SuperSonics|Subscription details');
export const licensedToHeaderText = s__('SuperSonics|Licensed to');
export const manageSubscriptionButtonText = s__('SuperSonics|Manage');
......@@ -8,13 +15,13 @@ export const copySubscriptionIdButtonText = __('Copy');
export const subscriptionTypeText = __('%{type} License');
export const detailsLabels = {
address: __('Address'),
id: s__('SuperSonics|ID'),
company: __('Company'),
email: __('Email'),
id: s__('SuperSonics|ID'),
lastSync: s__('SuperSonics|Last Sync'),
name: __('Name'),
plan: s__('SuperSonics|Plan'),
renews: s__('SuperSonics|Renews'),
expiresAt: s__('SuperSonics|Renews'),
startsAt: s__('SuperSonics|Started'),
};
......@@ -35,14 +42,23 @@ export const usersOverSubscriptionText = s__(
`CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement.`,
);
export const subscriptionTable = {
activatedOn: s__('SuperSonics|Activated on'),
activatedAt: s__('SuperSonics|Activated on'),
expiresOn: s__('SuperSonics|Expires on'),
seats: s__('SuperSonics|Seats'),
startsAt: s__('SuperSonics|Valid From'),
title: __('Subscription History'),
type: s__('SuperSonics|Type'),
validFrom: s__('SuperSonics|Valid From'),
};
export const subscriptionType = {
CLOUD: 'cloud',
LEGACY: 'legacy',
};
export const subscriptionQueries = {
query: getCurrentLicense,
mutation: activateSubscriptionMutation,
};
export const subscriptionHistoryQueries = {
query: getLicenseHistory,
};
query getCurrentLicense {
currentLicense {
id
type
plan
name
email
company
startsAt
expiresAt
activatedAt
lastSync
usersInLicenseCount
billableUsersCount
maximumUserCount
usersOverLicenseCount
}
}
query {
licenseHistoryEntries {
nodes {
id
type
plan
name
email
company
usersInLicenseCount
startsAt
expiresAt
activatedAt
}
}
}
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import CloudLicenseShowApp from '../components/app.vue';
Vue.use(VueApollo);
......@@ -16,14 +17,16 @@ export default () => {
return null;
}
const { planName } = el.dataset;
const { hasActiveLicense } = el.dataset;
return new Vue({
el,
apolloProvider,
provide: {
planName,
},
render: (h) => h(CloudLicenseShowApp),
render: (h) =>
h(CloudLicenseShowApp, {
props: {
hasActiveLicense: parseBoolean(hasActiveLicense),
},
}),
});
};
......@@ -16,6 +16,10 @@ module LicenseHelper
License.current&.plan&.titleize || 'Core'
end
def has_active_license?
License.current.present?
end
def new_trial_url
return_to_url = CGI.escape(Gitlab.config.gitlab.url)
uri = URI.parse(::EE::SUBSCRIPTIONS_URL)
......@@ -50,7 +54,7 @@ module LicenseHelper
def cloud_license_view_data
{
plan_name: current_license_title
has_active_license: (has_active_license? ? 'true' : 'false')
}
end
......
......@@ -16,11 +16,11 @@ RSpec.describe "Admin views Cloud License", :js do
context "#{plan} license" do
let_it_be(:license) { build(:license, plan: plan) }
it 'displays the correct license name' do
it 'displays the subscription details' do
visit(admin_cloud_license_path)
page.within(find('#content-body', match: :first)) do
expect(page).to have_content("This instance is currently using the #{plan.titleize} plan.")
expect(page).to have_content("Subscription details")
end
end
end
......@@ -33,9 +33,9 @@ RSpec.describe "Admin views Cloud License", :js do
visit(admin_cloud_license_path)
end
it "displays the fallback license name" do
it "displays a message signaling there is not active subscription" do
page.within(find('#content-body', match: :first)) do
expect(page).to have_content("This instance is currently using the Core plan.")
expect(page).to have_content("You do not have an active subscription")
end
end
end
......
import { shallowMount } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import CloudLicenseApp from 'ee/pages/admin/cloud_licenses/components/app.vue';
import CloudLicenseSubscriptionActivationForm from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import SubscriptionActivationForm from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import SubscriptionBreakdown from 'ee/pages/admin/cloud_licenses/components/subscription_breakdown.vue';
import {
subscriptionActivationTitle,
subscriptionHistoryQueries,
subscriptionMainTitle,
subscriptionQueries,
} from 'ee/pages/admin/cloud_licenses/constants';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license, subscriptionHistory } from '../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('CloudLicenseApp', () => {
let wrapper;
const findActivateSubscriptionForm = () =>
wrapper.findComponent(CloudLicenseSubscriptionActivationForm);
const findActivateSubscriptionForm = () => wrapper.findComponent(SubscriptionActivationForm);
const findSubscriptionBreakdown = () => wrapper.findComponent(SubscriptionBreakdown);
const findSubscriptionActivationTitle = () =>
wrapper.findByTestId('subscription-activation-title');
const findSubscriptionMainTitle = () => wrapper.findByTestId('subscription-main-title');
let currentSubscriptionResolver;
let subscriptionHistoryResolver;
const createMockApolloProvider = ([subscriptionResolver, historyResolver]) => {
localVue.use(VueApollo);
return createMockApollo([
[subscriptionQueries.query, subscriptionResolver],
[subscriptionHistoryQueries.query, historyResolver],
]);
};
const createComponent = (props = {}) => {
const createComponent = (props = {}, resolverMock) => {
wrapper = extendedWrapper(
shallowMount(CloudLicenseApp, {
localVue,
apolloProvider: createMockApolloProvider(resolverMock),
propsData: {
...props,
},
provide: {
planName: 'Core',
},
}),
);
};
afterEach(() => {
wrapper.destroy();
currentSubscriptionResolver.mockRestore();
subscriptionHistoryResolver.mockRestore();
});
describe('Subscription Activation Form', () => {
beforeEach(() => createComponent());
beforeEach(() => {
currentSubscriptionResolver = jest
.fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest
.fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]);
});
it('presents a form', () => {
expect(findActivateSubscriptionForm().exists()).toBe(true);
it('shows the main title', () => {
expect(findSubscriptionMainTitle().text()).toBe(subscriptionMainTitle);
});
it('presents a main title with the plan name', () => {
expect(wrapper.text()).toContain('Core plan');
describe('without an active license', () => {
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);
});
it('shows the subscription activation form', () => {
expect(findActivateSubscriptionForm().exists()).toBe(true);
});
});
describe('with active license', () => {
beforeEach(() => {
currentSubscriptionResolver = jest
.fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest
.fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } });
createComponent({ hasActiveLicense: true }, [
currentSubscriptionResolver,
subscriptionHistoryResolver,
]);
});
it('queries for the current license', () => {
expect(currentSubscriptionResolver).toHaveBeenCalledTimes(1);
});
it('queries for the current history', () => {
expect(subscriptionHistoryResolver).toHaveBeenCalledTimes(1);
});
it('passes the correct data to the subscription breakdown', () => {
expect(findSubscriptionBreakdown().props()).toMatchObject({
subscription: license.ULTIMATE,
subscriptionList: subscriptionHistory,
});
});
});
});
});
......@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import CloudLicenseSubscriptionActivationForm, {
SUBSCRIPTION_ACTIVATION_EVENT,
} from 'ee/pages/admin/cloud_licenses/components/subscription_activation_form.vue';
import activateSubscriptionMutation from 'ee/pages/admin/cloud_licenses/graphql/mutations/activate_subscription.mutation.graphql';
import { subscriptionQueries } from 'ee/pages/admin/cloud_licenses/constants';
import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
......@@ -21,7 +21,7 @@ describe('CloudLicenseApp', () => {
const createMockApolloProvider = (resolverMock) => {
localVue.use(VueApollo);
return createMockApollo([[activateSubscriptionMutation, resolverMock]]);
return createMockApollo([[subscriptionQueries.mutation, resolverMock]]);
};
const findActivateButton = () => wrapper.findByTestId('activate-button');
......@@ -123,7 +123,7 @@ describe('CloudLicenseApp', () => {
});
it('emits a successful event', () => {
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_EVENT)).toEqual([[fakeActivationCode]]);
expect(wrapper.emitted(SUBSCRIPTION_ACTIVATION_EVENT)).toEqual([[true]]);
});
});
......
......@@ -91,17 +91,28 @@ describe('Subscription Breakdown', () => {
});
});
describe('with empty data', () => {
describe('with no subscription data', () => {
it('does not show user info', () => {
createComponent({ props: { subscription: {} } });
expect(findDetailsUserInfo().exists()).toBe(false);
});
it('does not show subscription history', () => {
it('shows the current subscription as the only history item', () => {
createComponent({ props: { subscription: {}, subscriptionList: [] } });
expect(findDetailsUserInfo().exists()).toBe(false);
});
});
describe('with no subscription history data', () => {
it('shows the current subscription as the only history item', () => {
createComponent({ props: { subscriptionList: [] } });
expect(findDetailsHistory().exists()).toBe(false);
expect(findDetailsHistory().props('')).toMatchObject({
currentSubscriptionId: license.ULTIMATE.id,
subscriptionList: [license.ULTIMATE],
});
});
});
});
import { GlCard } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { subscriptionDetailsFields } from 'ee/pages/admin/cloud_licenses/components/subscription_breakdown.vue';
import SubscriptionDetailsCard from 'ee/pages/admin/cloud_licenses/components/subscription_details_card.vue';
import SubscriptionDetailsTable from 'ee/pages/admin/cloud_licenses/components/subscription_details_table.vue';
import { useFakeDate } from 'helpers/fake_date';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license } from '../mock_data';
describe('Subscription Details Card', () => {
// March 16th, 2020
useFakeDate(2021, 2, 16);
let wrapper;
const findCard = () => wrapper.findComponent(GlCard);
......@@ -14,7 +19,7 @@ describe('Subscription Details Card', () => {
const findSubscriptionDetailsTable = () => wrapper.findComponent(SubscriptionDetailsTable);
const createComponent = (
{ detailsFields = ['id', 'plan'], headerText, subscription = license.ULTIMATE } = {},
{ detailsFields = subscriptionDetailsFields, headerText, subscription = license.ULTIMATE } = {},
slots,
) => {
wrapper = extendedWrapper(
......@@ -56,13 +61,28 @@ describe('Subscription Details Card', () => {
{
canCopy: true,
label: 'ID',
value: '1309188',
value: 13,
},
{
canCopy: false,
label: 'Plan',
value: 'Ultimate',
},
{
canCopy: false,
label: 'Renews',
value: 'in 1 year',
},
{
canCopy: false,
label: 'Last Sync',
value: 'just now',
},
{
canCopy: false,
label: 'Started',
value: '11 March 2021',
},
]);
});
});
......
......@@ -62,15 +62,14 @@ describe('Subscription Details History', () => {
});
it.each`
testId | key
${'name'} | ${'name'}
${'email'} | ${'email'}
${'company'} | ${'company'}
${'plan'} | ${'plan'}
${'starts-at'} | ${'startsAt'}
${'valid-from'} | ${'validFrom'}
${'expires-at'} | ${'expiresAt'}
${'users-in-license'} | ${'usersInLicense'}
testId | key
${'name'} | ${'name'}
${'email'} | ${'email'}
${'company'} | ${'company'}
${'starts-at'} | ${'startsAt'}
${'starts-at'} | ${'startsAt'}
${'expires-at'} | ${'expiresAt'}
${'users-in-license-count'} | ${'usersInLicenseCount'}
`('displays the correct value for the $testId cell', ({ testId, key }) => {
const cellTestId = `subscription-cell-${testId}`;
expect(findCellByTestid(cellTestId).text()).toBe(subscriptionHistory[0][key]);
......@@ -80,6 +79,11 @@ describe('Subscription Details History', () => {
const cellTestId = `subscription-cell-type`;
expect(findCellByTestid(cellTestId).text()).toBe('Cloud License');
});
it('displays the correct value for the plan cell', () => {
const cellTestId = `subscription-cell-plan`;
expect(findCellByTestid(cellTestId).text()).toBe('Ultimate');
});
});
});
......
......@@ -17,7 +17,7 @@ import {
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license } from '../mock_data';
describe('Subscription Details Card', () => {
describe('Subscription Details User Info', () => {
let wrapper;
const itif = (condition) => (condition ? it : it.skip);
......@@ -42,11 +42,11 @@ describe('Subscription Details Card', () => {
});
describe.each`
testId | info | title | text | link
${'users-in-license'} | ${'10'} | ${usersInSubscriptionTitle} | ${usersInSubscriptionText} | ${false}
${'billable-users'} | ${'8'} | ${billableUsersTitle} | ${billableUsersText} | ${billableUsersURL}
${'maximum-users'} | ${'8'} | ${maximumUsersTitle} | ${maximumUsersText} | ${false}
${'users-over-subscription'} | ${'0'} | ${usersOverSubscriptionTitle} | ${usersOverSubscriptionText} | ${trueUpURL}
testId | info | title | text | link
${'users-in-license'} | ${'10'} | ${usersInSubscriptionTitle} | ${usersInSubscriptionText} | ${false}
${'billable-users'} | ${'8'} | ${billableUsersTitle} | ${billableUsersText} | ${billableUsersURL}
${'maximum-users'} | ${'8'} | ${maximumUsersTitle} | ${maximumUsersText} | ${false}
${'users-over-license'} | ${'0'} | ${usersOverSubscriptionTitle} | ${usersOverSubscriptionText} | ${trueUpURL}
`('with data for $card', ({ testId, info, title, text, link }) => {
beforeEach(() => {
createComponent();
......
......@@ -2,47 +2,47 @@ import { subscriptionType } from 'ee/pages/admin/cloud_licenses/constants';
export const license = {
ULTIMATE: {
billableUsers: '8',
activatedAt: '2022-03-16',
billableUsersCount: '8',
expiresAt: '2022-03-16',
company: 'ACME Corp',
email: 'user@acmecorp.com',
id: '1309188',
lastSync: 'just now - actual date',
maximumUsers: '8',
id: 'gid://gitlab/License/13',
lastSync: '2021-03-16T00:00:00.000',
maximumUserCount: '8',
name: 'Jane Doe',
plan: 'Ultimate',
startsAt: '22 February',
renews: 'in 11 months',
usersInLicense: '10',
usersOverSubscription: '0',
plan: 'ultimate',
startsAt: '2021-03-11',
type: subscriptionType.CLOUD,
usersInLicenseCount: '10',
usersOverLicenseCount: '0',
},
};
export const subscriptionHistory = [
{
activatedAt: '2022-03-16',
company: 'ACME Corp',
email: 'user@acmecorp.com',
expiresAt: '15-03-2022',
// TODO: verify presence in graphQL response
id: '1309188',
expiresAt: '2022-03-16',
id: 'gid://gitlab/License/13',
name: 'Jane Doe',
plan: 'Ultimate',
startsAt: '16-03-2021',
plan: 'ultimate',
startsAt: '2021-03-11',
type: subscriptionType.CLOUD,
validFrom: '16-03-2021',
usersInLicense: '10',
usersInLicenseCount: '10',
},
{
activatedAt: '2020-11-05',
company: 'ACME Corp',
email: 'user@acmecorp.com',
expiresAt: '30-06-2021',
// TODO: verify presence in graphQL response
id: '000000000',
expiresAt: '2021-03-16',
id: 'gid://gitlab/License/11',
name: 'Jane Doe',
plan: 'Ultimate',
startsAt: '01-07-2020',
plan: 'premium',
startsAt: '2020-03-16',
type: subscriptionType.LEGACY,
validFrom: '01-07-2020',
usersInLicense: '5',
usersInLicenseCount: '5',
},
];
......
......@@ -86,7 +86,7 @@ RSpec.describe LicenseHelper do
license = double('License', plan: custom_plan)
allow(License).to receive(:current).and_return(license)
expect(cloud_license_view_data).to eq({ plan_name: 'Custom Plan' })
expect(cloud_license_view_data).to eq({ has_active_license: 'true' })
end
end
......@@ -94,7 +94,7 @@ RSpec.describe LicenseHelper do
it 'returns the data for the view' do
allow(License).to receive(:current).and_return(nil)
expect(cloud_license_view_data).to eq({ plan_name: 'Core' })
expect(cloud_license_view_data).to eq({ has_active_license: 'false' })
end
end
end
......
......@@ -6656,9 +6656,6 @@ msgstr ""
msgid "CloudLicense|Paste your activation code"
msgstr ""
msgid "CloudLicense|This instance is currently using the %{planName} plan."
msgstr ""
msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
msgstr ""
......@@ -6677,9 +6674,6 @@ msgstr ""
msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr ""
msgid "CloudLicense|Your subscription"
msgstr ""
msgid "Cluster"
msgstr ""
......@@ -30378,6 +30372,12 @@ msgstr ""
msgid "SuperSonics|Valid From"
msgstr ""
msgid "SuperSonics|You do not have an active subscription"
msgstr ""
msgid "SuperSonics|Your subscription"
msgstr ""
msgid "Support"
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