Commit ad7f40bc authored by mlunoe's avatar mlunoe

Feat(SM: Subscription History): add future subscr

Add future subscriptions to the subscription
history table for self-managed users

Changelog: added
EE: true
parent 965fd314
...@@ -11,13 +11,15 @@ import { ...@@ -11,13 +11,15 @@ import {
subscriptionHistoryFailedTitle, subscriptionHistoryFailedTitle,
subscriptionHistoryFailedMessage, subscriptionHistoryFailedMessage,
currentSubscriptionsEntryName, currentSubscriptionsEntryName,
historySubscriptionsEntryName, pastSubscriptionsEntryName,
futureSubscriptionsEntryName,
subscriptionMainTitle, subscriptionMainTitle,
exportLicenseUsageBtnText, exportLicenseUsageBtnText,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT, SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from '../constants'; } from '../constants';
import getCurrentLicense from '../graphql/queries/get_current_license.query.graphql'; import getCurrentLicense from '../graphql/queries/get_current_license.query.graphql';
import getLicenseHistory from '../graphql/queries/get_license_history.query.graphql'; import getPastLicenseHistory from '../graphql/queries/get_past_license_history.query.graphql';
import getFutureLicenseHistory from '../graphql/queries/get_future_license_history.query.graphql';
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';
import SubscriptionPurchaseCard from './subscription_purchase_card.vue'; import SubscriptionPurchaseCard from './subscription_purchase_card.vue';
...@@ -63,21 +65,31 @@ export default { ...@@ -63,21 +65,31 @@ export default {
this.subscriptionFetchError = currentSubscriptionsEntryName; this.subscriptionFetchError = currentSubscriptionsEntryName;
}, },
}, },
subscriptionHistory: { pastLicenseHistoryEntries: {
query: getLicenseHistory, query: getPastLicenseHistory,
update({ licenseHistoryEntries }) { update({ licenseHistoryEntries }) {
return licenseHistoryEntries?.nodes || []; return licenseHistoryEntries?.nodes || [];
}, },
error() { error() {
this.subscriptionFetchError = historySubscriptionsEntryName; this.subscriptionFetchError = pastSubscriptionsEntryName;
},
},
futureLicenseHistoryEntries: {
query: getFutureLicenseHistory,
update({ subscriptionFutureEntries }) {
return subscriptionFutureEntries?.nodes || [];
},
error() {
this.subscriptionFetchError = futureSubscriptionsEntryName;
}, },
}, },
}, },
data() { data() {
return { return {
currentSubscription: {}, currentSubscription: {},
pastLicenseHistoryEntries: [],
futureLicenseHistoryEntries: [],
activationNotification: null, activationNotification: null,
subscriptionHistory: [],
subscriptionFetchError: null, subscriptionFetchError: null,
}; };
}, },
...@@ -88,6 +100,9 @@ export default { ...@@ -88,6 +100,9 @@ export default {
canShowSubscriptionDetails() { canShowSubscriptionDetails() {
return this.hasActiveLicense || this.hasValidSubscriptionData; return this.hasActiveLicense || this.hasValidSubscriptionData;
}, },
subscriptionHistory() {
return [...this.futureLicenseHistoryEntries, ...this.pastLicenseHistoryEntries];
},
}, },
created() { created() {
this.$options.activationListeners = { this.$options.activationListeners = {
......
...@@ -64,6 +64,13 @@ export default { ...@@ -64,6 +64,13 @@ export default {
}, },
{ {
key: 'activatedAt', key: 'activatedAt',
formatter: (v, k, { activatedAt }) => {
if (!activatedAt) {
return '-';
}
return activatedAt;
},
label: subscriptionTable.activatedAt, label: subscriptionTable.activatedAt,
tdAttr, tdAttr,
tdClass: this.cellClass, tdClass: this.cellClass,
...@@ -109,11 +116,9 @@ export default { ...@@ -109,11 +116,9 @@ export default {
isCurrentSubscription({ id }) { isCurrentSubscription({ id }) {
return id === this.currentSubscriptionId; return id === this.currentSubscriptionId;
}, },
rowAttr(item) { rowAttr() {
return { return {
'data-testid': this.isCurrentSubscription(item) 'data-testid': 'subscription-history-row',
? 'subscription-current'
: 'subscription-history-row',
}; };
}, },
rowClass(item) { rowClass(item) {
......
...@@ -22,7 +22,8 @@ export const subscriptionHistoryFailedMessage = s__( ...@@ -22,7 +22,8 @@ export const subscriptionHistoryFailedMessage = s__(
'SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again.', 'SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again.',
); );
export const currentSubscriptionsEntryName = s__('SuperSonics|current subscription'); export const currentSubscriptionsEntryName = s__('SuperSonics|current subscription');
export const historySubscriptionsEntryName = s__('SuperSonics|history subscriptions'); export const pastSubscriptionsEntryName = s__('SuperSonics|past subscriptions');
export const futureSubscriptionsEntryName = s__('SuperSonics|future subscriptions');
export const cancelLabel = __('Cancel'); export const cancelLabel = __('Cancel');
export const activateLabel = s__('AdminUsers|Activate'); export const activateLabel = s__('AdminUsers|Activate');
......
query getFutureLicenseHistory {
subscriptionFutureEntries {
nodes {
type
plan
name
email
company
usersInLicenseCount
startsAt
expiresAt
}
}
}
import produce from 'immer'; import produce from 'immer';
import getCurrentLicense from './queries/get_current_license.query.graphql'; import getCurrentLicense from './queries/get_current_license.query.graphql';
import getLicenseHistory from './queries/get_license_history.query.graphql'; import getPastLicenseHistory from './queries/get_past_license_history.query.graphql';
export const getLicenseFromData = ({ data } = {}) => data?.gitlabSubscriptionActivate?.license; export const getLicenseFromData = ({ data } = {}) => data?.gitlabSubscriptionActivate?.license;
export const getErrorsAsData = ({ data } = {}) => data?.gitlabSubscriptionActivate?.errors || []; export const getErrorsAsData = ({ data } = {}) => data?.gitlabSubscriptionActivate?.errors || [];
...@@ -14,12 +14,12 @@ export const updateSubscriptionAppCache = (cache, mutation) => { ...@@ -14,12 +14,12 @@ export const updateSubscriptionAppCache = (cache, mutation) => {
draftData.currentLicense = license; draftData.currentLicense = license;
}); });
cache.writeQuery({ query: getCurrentLicense, data }); cache.writeQuery({ query: getCurrentLicense, data });
const subscriptionsList = cache.readQuery({ query: getLicenseHistory }); const pastSubscriptions = cache.readQuery({ query: getPastLicenseHistory });
const subscriptionListData = produce(subscriptionsList, (draftData) => { const pastSubscriptionsData = produce(pastSubscriptions, (draftData) => {
draftData.licenseHistoryEntries.nodes = [ draftData.licenseHistoryEntries.nodes = [
license, license,
...subscriptionsList.licenseHistoryEntries.nodes, ...pastSubscriptions.licenseHistoryEntries.nodes,
]; ];
}); });
cache.writeQuery({ query: getLicenseHistory, data: subscriptionListData }); cache.writeQuery({ query: getPastLicenseHistory, data: pastSubscriptionsData });
}; };
...@@ -12,18 +12,20 @@ import { ...@@ -12,18 +12,20 @@ import {
subscriptionHistoryFailedTitle, subscriptionHistoryFailedTitle,
subscriptionHistoryFailedMessage, subscriptionHistoryFailedMessage,
currentSubscriptionsEntryName, currentSubscriptionsEntryName,
historySubscriptionsEntryName, pastSubscriptionsEntryName,
futureSubscriptionsEntryName,
subscriptionMainTitle, subscriptionMainTitle,
SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT, SUBSCRIPTION_ACTIVATION_SUCCESS_EVENT,
} from 'ee/admin/subscriptions/show/constants'; } from 'ee/admin/subscriptions/show/constants';
import getCurrentLicense from 'ee/admin/subscriptions/show/graphql/queries/get_current_license.query.graphql'; import getCurrentLicense from 'ee/admin/subscriptions/show/graphql/queries/get_current_license.query.graphql';
import getLicenseHistory from 'ee/admin/subscriptions/show/graphql/queries/get_license_history.query.graphql'; import getPastLicenseHistory from 'ee/admin/subscriptions/show/graphql/queries/get_past_license_history.query.graphql';
import getFutureLicenseHistory from 'ee/admin/subscriptions/show/graphql/queries/get_future_license_history.query.graphql';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { useFakeDate } from 'helpers/fake_date'; 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 { sprintf } from '~/locale'; import { sprintf } from '~/locale';
import { license, subscriptionHistory } from '../mock_data'; import { license, subscriptionPastHistory, subscriptionFutureHistory } from '../mock_data';
Vue.use(VueApollo); Vue.use(VueApollo);
...@@ -45,12 +47,14 @@ describe('SubscriptionManagementApp', () => { ...@@ -45,12 +47,14 @@ describe('SubscriptionManagementApp', () => {
const findExportLicenseUsageFileLink = () => wrapper.findComponent(GlButton); const findExportLicenseUsageFileLink = () => wrapper.findComponent(GlButton);
let currentSubscriptionResolver; let currentSubscriptionResolver;
let subscriptionHistoryResolver; let pastSubscriptionsResolver;
const createMockApolloProvider = ([subscriptionResolver, historyResolver]) => { let futureSubscriptionsResolver;
const createMockApolloProvider = ([currentResolver, pastResolver, futureResolver]) => {
Vue.use(VueApollo); Vue.use(VueApollo);
return createMockApollo([ return createMockApollo([
[getCurrentLicense, subscriptionResolver], [getCurrentLicense, currentResolver],
[getLicenseHistory, historyResolver], [getPastLicenseHistory, pastResolver],
[getFutureLicenseHistory, futureResolver],
]); ]);
}; };
...@@ -76,34 +80,54 @@ describe('SubscriptionManagementApp', () => { ...@@ -76,34 +80,54 @@ describe('SubscriptionManagementApp', () => {
describe('when failing to fetch subcriptions', () => { describe('when failing to fetch subcriptions', () => {
describe('when failing to fetch history subcriptions', () => { describe('when failing to fetch history subcriptions', () => {
describe.each` describe.each`
currentFails | historyFails currentFails | pastFails | futureFails
${true} | ${false} ${true} | ${false} | ${false}
${false} | ${true} ${false} | ${true} | ${false}
${true} | ${true} ${false} | ${false} | ${true}
${true} | ${true} | ${false}
${false} | ${true} | ${true}
${true} | ${false} | ${true}
${true} | ${true} | ${true}
`( `(
'with current subscription failing to fetch=$currentFails and history subscriptions failing to fetch=$historyFails', 'with current subscription fetch failing: currentFails=$currentFails, pastFails=$pastFails, and futureFails=$futureFails',
({ currentFails, historyFails }) => { ({ currentFails, pastFails, futureFails }) => {
const error = new Error('Network error!'); const error = new Error('Network error!');
beforeEach(async () => { beforeEach(async () => {
currentSubscriptionResolver = currentFails currentSubscriptionResolver = currentFails
? jest.fn().mockRejectedValue({ error }) ? jest.fn().mockRejectedValue({ error })
: jest.fn().mockResolvedValue({ data: { currentLicense: license.ULTIMATE } }); : jest.fn().mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = historyFails pastSubscriptionsResolver = pastFails
? jest.fn().mockRejectedValue({ error }) ? jest.fn().mockRejectedValue({ error })
: jest.fn().mockResolvedValue({ : jest.fn().mockResolvedValue({
data: { licenseHistoryEntries: { nodes: subscriptionHistory } }, data: { licenseHistoryEntries: { nodes: subscriptionPastHistory } },
});
futureSubscriptionsResolver = futureFails
? jest.fn().mockRejectedValue({ error })
: jest.fn().mockResolvedValue({
data: { subscriptionFutureEntries: { nodes: subscriptionFutureHistory } },
}); });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]); createComponent({}, [
currentSubscriptionResolver,
pastSubscriptionsResolver,
futureSubscriptionsResolver,
]);
await waitForPromises(); await waitForPromises();
}); });
it('renders the error alert', () => { it('renders the error alert', () => {
const alert = findSubscriptionFetchErrorAlert(); const alert = findSubscriptionFetchErrorAlert();
const subscriptionEntryName = historyFails let subscriptionEntryName;
? historySubscriptionsEntryName if (currentFails) {
: currentSubscriptionsEntryName; subscriptionEntryName = currentSubscriptionsEntryName;
}
if (pastFails) {
subscriptionEntryName = pastSubscriptionsEntryName;
}
if (futureFails) {
subscriptionEntryName = futureSubscriptionsEntryName;
}
expect(alert.exists()).toBe(true); expect(alert.exists()).toBe(true);
expect(alert.props('title')).toBe(subscriptionHistoryFailedTitle); expect(alert.props('title')).toBe(subscriptionHistoryFailedTitle);
expect(alert.text().replace(/\s+/g, ' ')).toBe( expect(alert.text().replace(/\s+/g, ' ')).toBe(
...@@ -120,10 +144,17 @@ describe('SubscriptionManagementApp', () => { ...@@ -120,10 +144,17 @@ describe('SubscriptionManagementApp', () => {
currentSubscriptionResolver = jest currentSubscriptionResolver = jest
.fn() .fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } }); .mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest pastSubscriptionsResolver = jest.fn().mockResolvedValue({
.fn() data: { licenseHistoryEntries: { nodes: subscriptionPastHistory } },
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } }); });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]); futureSubscriptionsResolver = jest.fn().mockResolvedValue({
data: { subscriptionFutureEntries: { nodes: subscriptionFutureHistory } },
});
createComponent({}, [
currentSubscriptionResolver,
pastSubscriptionsResolver,
futureSubscriptionsResolver,
]);
expect(findSubscriptionMainTitle().text()).toBe(subscriptionMainTitle); expect(findSubscriptionMainTitle().text()).toBe(subscriptionMainTitle);
}); });
...@@ -132,17 +163,29 @@ describe('SubscriptionManagementApp', () => { ...@@ -132,17 +163,29 @@ describe('SubscriptionManagementApp', () => {
currentSubscriptionResolver = jest currentSubscriptionResolver = jest
.fn() .fn()
.mockResolvedValue({ data: { currentLicense: null } }); .mockResolvedValue({ data: { currentLicense: null } });
subscriptionHistoryResolver = jest pastSubscriptionsResolver = jest
.fn() .fn()
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: [] } } }); .mockResolvedValue({ data: { licenseHistoryEntries: { nodes: [] } } });
createComponent({}, [currentSubscriptionResolver, subscriptionHistoryResolver]); futureSubscriptionsResolver = jest
.fn()
.mockResolvedValue({ data: { subscriptionFutureEntries: { nodes: [] } } });
createComponent({}, [
currentSubscriptionResolver,
pastSubscriptionsResolver,
futureSubscriptionsResolver,
]);
}); });
it('shows a title saying there is no active subscription', () => { it('shows a title saying there is no active subscription', () => {
expect(findSubscriptionActivationTitle().text()).toBe(noActiveSubscription); expect(findSubscriptionActivationTitle().text()).toBe(noActiveSubscription);
}); });
it('queries for the current history', () => { it('queries for the past history', () => {
expect(subscriptionHistoryResolver).toHaveBeenCalledTimes(1); expect(pastSubscriptionsResolver).toHaveBeenCalledTimes(1);
});
it('queries for the future history', () => {
expect(futureSubscriptionsResolver).toHaveBeenCalledTimes(1);
}); });
it('shows the subscription activation form', () => { it('shows the subscription activation form', () => {
...@@ -185,12 +228,16 @@ describe('SubscriptionManagementApp', () => { ...@@ -185,12 +228,16 @@ describe('SubscriptionManagementApp', () => {
currentSubscriptionResolver = jest currentSubscriptionResolver = jest
.fn() .fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } }); .mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest pastSubscriptionsResolver = jest.fn().mockResolvedValue({
.fn() data: { licenseHistoryEntries: { nodes: subscriptionPastHistory } },
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } }); });
futureSubscriptionsResolver = jest.fn().mockResolvedValue({
data: { subscriptionFutureEntries: { nodes: subscriptionFutureHistory } },
});
createComponent({ hasActiveLicense: false }, [ createComponent({ hasActiveLicense: false }, [
currentSubscriptionResolver, currentSubscriptionResolver,
subscriptionHistoryResolver, pastSubscriptionsResolver,
futureSubscriptionsResolver,
]); ]);
await waitForPromises(); await waitForPromises();
}); });
...@@ -198,7 +245,7 @@ describe('SubscriptionManagementApp', () => { ...@@ -198,7 +245,7 @@ describe('SubscriptionManagementApp', () => {
it('passes the correct data to the subscription breakdown', () => { it('passes the correct data to the subscription breakdown', () => {
expect(findSubscriptionBreakdown().props()).toMatchObject({ expect(findSubscriptionBreakdown().props()).toMatchObject({
subscription: license.ULTIMATE, subscription: license.ULTIMATE,
subscriptionList: subscriptionHistory, subscriptionList: [...subscriptionFutureHistory, ...subscriptionPastHistory],
}); });
}); });
...@@ -228,12 +275,16 @@ describe('SubscriptionManagementApp', () => { ...@@ -228,12 +275,16 @@ describe('SubscriptionManagementApp', () => {
currentSubscriptionResolver = jest currentSubscriptionResolver = jest
.fn() .fn()
.mockResolvedValue({ data: { currentLicense: license.ULTIMATE } }); .mockResolvedValue({ data: { currentLicense: license.ULTIMATE } });
subscriptionHistoryResolver = jest pastSubscriptionsResolver = jest.fn().mockResolvedValue({
.fn() data: { licenseHistoryEntries: { nodes: subscriptionPastHistory } },
.mockResolvedValue({ data: { licenseHistoryEntries: { nodes: subscriptionHistory } } }); });
futureSubscriptionsResolver = jest.fn().mockResolvedValue({
data: { subscriptionFutureEntries: { nodes: subscriptionFutureHistory } },
});
createComponent({ hasActiveLicense: true }, [ createComponent({ hasActiveLicense: true }, [
currentSubscriptionResolver, currentSubscriptionResolver,
subscriptionHistoryResolver, pastSubscriptionsResolver,
futureSubscriptionsResolver,
]); ]);
await waitForPromises(); await waitForPromises();
}); });
...@@ -242,14 +293,18 @@ describe('SubscriptionManagementApp', () => { ...@@ -242,14 +293,18 @@ describe('SubscriptionManagementApp', () => {
expect(currentSubscriptionResolver).toHaveBeenCalledTimes(1); expect(currentSubscriptionResolver).toHaveBeenCalledTimes(1);
}); });
it('queries for the current history', () => { it('queries for the past history', () => {
expect(subscriptionHistoryResolver).toHaveBeenCalledTimes(1); expect(pastSubscriptionsResolver).toHaveBeenCalledTimes(1);
});
it('queries for the future history', () => {
expect(futureSubscriptionsResolver).toHaveBeenCalledTimes(1);
}); });
it('passes the correct data to the subscription breakdown', () => { it('passes the correct data to the subscription breakdown', () => {
expect(findSubscriptionBreakdown().props()).toMatchObject({ expect(findSubscriptionBreakdown().props()).toMatchObject({
subscription: license.ULTIMATE, subscription: license.ULTIMATE,
subscriptionList: subscriptionHistory, subscriptionList: [...subscriptionFutureHistory, ...subscriptionPastHistory],
}); });
}); });
......
...@@ -27,7 +27,7 @@ import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisse ...@@ -27,7 +27,7 @@ import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisse
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { license, subscriptionHistory } from '../mock_data'; import { license, subscriptionPastHistory, subscriptionFutureHistory } from '../mock_data';
describe('Subscription Breakdown', () => { describe('Subscription Breakdown', () => {
let axiosMock; let axiosMock;
...@@ -35,7 +35,7 @@ describe('Subscription Breakdown', () => { ...@@ -35,7 +35,7 @@ describe('Subscription Breakdown', () => {
let glModalDirective; let glModalDirective;
let userCalloutDismissSpy; let userCalloutDismissSpy;
const [, licenseFile] = subscriptionHistory; const [, licenseFile] = subscriptionPastHistory;
const congratulationSvgPath = '/path/to/svg'; const congratulationSvgPath = '/path/to/svg';
const connectivityHelpURL = 'connectivity/help/url'; const connectivityHelpURL = 'connectivity/help/url';
const customersPortalUrl = 'customers.dot'; const customersPortalUrl = 'customers.dot';
...@@ -88,7 +88,7 @@ describe('Subscription Breakdown', () => { ...@@ -88,7 +88,7 @@ describe('Subscription Breakdown', () => {
}, },
propsData: { propsData: {
subscription: license.ULTIMATE, subscription: license.ULTIMATE,
subscriptionList: subscriptionHistory, subscriptionList: [...subscriptionFutureHistory, ...subscriptionPastHistory],
...props, ...props,
}, },
stubs: { stubs: {
...@@ -398,7 +398,10 @@ describe('Subscription Breakdown', () => { ...@@ -398,7 +398,10 @@ describe('Subscription Breakdown', () => {
it('provides the correct props to the subscription history component', () => { it('provides the correct props to the subscription history component', () => {
expect(findDetailsHistory().props('currentSubscriptionId')).toBe(license.ULTIMATE.id); expect(findDetailsHistory().props('currentSubscriptionId')).toBe(license.ULTIMATE.id);
expect(findDetailsHistory().props('subscriptionList')).toBe(subscriptionHistory); expect(findDetailsHistory().props('subscriptionList')).toMatchObject([
...subscriptionFutureHistory,
...subscriptionPastHistory,
]);
}); });
}); });
......
import { GlBadge, GlIcon, GlTooltip } from '@gitlab/ui'; import { GlBadge, GlIcon, GlTooltip } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import SubscriptionDetailsHistory from 'ee/admin/subscriptions/show/components/subscription_details_history.vue'; import SubscriptionDetailsHistory from 'ee/admin/subscriptions/show/components/subscription_details_history.vue';
import { detailsLabels, cloudLicenseText } from 'ee/admin/subscriptions/show/constants'; import {
detailsLabels,
cloudLicenseText,
licenseFileText,
subscriptionTypes,
} from 'ee/admin/subscriptions/show/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { license, subscriptionHistory } from '../mock_data'; import { license, subscriptionFutureHistory, subscriptionPastHistory } from '../mock_data';
const subscriptionList = [...subscriptionFutureHistory, ...subscriptionPastHistory];
const currentSubscriptionIndex = subscriptionFutureHistory.length;
describe('Subscription Details History', () => { describe('Subscription Details History', () => {
let wrapper; let wrapper;
const findCurrentRow = () => wrapper.findByTestId('subscription-current');
const findTableRows = () => wrapper.findAllByTestId('subscription-history-row'); const findTableRows = () => wrapper.findAllByTestId('subscription-history-row');
const findCurrentRow = () => findTableRows().at(currentSubscriptionIndex);
const cellFinder = (row) => (testId) => extendedWrapper(row).findByTestId(testId); const cellFinder = (row) => (testId) => extendedWrapper(row).findByTestId(testId);
const containsABadge = (row) => row.findComponent(GlBadge).exists(); const containsABadge = (row) => row.findComponent(GlBadge).exists();
const containsATooltip = (row) => row.findComponent(GlTooltip).exists(); const containsATooltip = (row) => row.findComponent(GlTooltip).exists();
...@@ -20,7 +29,7 @@ describe('Subscription Details History', () => { ...@@ -20,7 +29,7 @@ describe('Subscription Details History', () => {
mount(SubscriptionDetailsHistory, { mount(SubscriptionDetailsHistory, {
propsData: { propsData: {
currentSubscriptionId: license.ULTIMATE.id, currentSubscriptionId: license.ULTIMATE.id,
subscriptionList: subscriptionHistory, subscriptionList,
...props, ...props,
}, },
}), }),
...@@ -41,12 +50,12 @@ describe('Subscription Details History', () => { ...@@ -41,12 +50,12 @@ describe('Subscription Details History', () => {
}); });
it('has the correct number of subscription rows', () => { it('has the correct number of subscription rows', () => {
expect(findTableRows()).toHaveLength(1); expect(findTableRows()).toHaveLength(subscriptionList.length);
}); });
it('has the correct license type', () => { it('has the correct license type', () => {
expect(findCurrentRow().text()).toContain(cloudLicenseText); expect(findCurrentRow().text()).toContain(cloudLicenseText);
expect(findTableRows().at(0).text()).toContain('License file'); expect(findTableRows().at(-1).text()).toContain('License file');
}); });
it('has a badge for the license type', () => { it('has a badge for the license type', () => {
...@@ -73,49 +82,53 @@ describe('Subscription Details History', () => { ...@@ -73,49 +82,53 @@ describe('Subscription Details History', () => {
expect(findTableRows().at(0).classes('gl-text-blue-500')).toBe(false); expect(findTableRows().at(0).classes('gl-text-blue-500')).toBe(false);
}); });
describe('cell data', () => { describe.each(Object.entries(subscriptionList))('cell data index=%#', (index, subscription) => {
let findCellByTestid; let findCellByTestid;
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
findCellByTestid = cellFinder(findCurrentRow()); findCellByTestid = cellFinder(findTableRows().at(index));
}); });
it.each` it.each`
testId | key testId | key
${'starts-at'} | ${'startsAt'} ${'starts-at'} | ${'startsAt'}
${'starts-at'} | ${'startsAt'}
${'expires-at'} | ${'expiresAt'} ${'expires-at'} | ${'expiresAt'}
${'users-in-license-count'} | ${'usersInLicenseCount'} ${'users-in-license-count'} | ${'usersInLicenseCount'}
`('displays the correct value for the $testId cell', ({ testId, key }) => { `('displays the correct value for the $testId cell', ({ testId, key }) => {
const cellTestId = `subscription-cell-${testId}`; const cellTestId = `subscription-cell-${testId}`;
expect(findCellByTestid(cellTestId).text()).toBe(subscriptionHistory[0][key]); const value = subscription[key] || '-';
expect(findCellByTestid(cellTestId).text()).toBe(value);
}); });
it('displays the name field with tooltip', () => { it('displays the name field with tooltip', () => {
const cellTestId = 'subscription-cell-name'; const cellTestId = 'subscription-cell-name';
const text = findCellByTestid(cellTestId).text(); const text = findCellByTestid(cellTestId).text();
expect(text).toContain(subscriptionHistory[0].name); expect(text).toContain(subscription.name);
expect(text).toContain(`(${subscriptionHistory[0].company})`); expect(text).toContain(`(${subscription.company})`);
expect(text).toContain(subscriptionHistory[0].email); expect(text).toContain(subscription.email);
}); });
it('displays sr-only element for screen readers', () => { it('displays sr-only element for screen readers', () => {
const testId = 'subscription-history-sr-only'; const testId = 'subscription-history-sr-only';
const text = findCellByTestid(testId).text(); const text = findCellByTestid(testId).text();
expect(text).not.toContain(subscriptionHistory[0].name); expect(text).not.toContain(subscription.name);
expect(text).toContain(`(${detailsLabels.company}: ${subscriptionHistory[0].company})`); expect(text).toContain(`(${detailsLabels.company}: ${subscription.company})`);
expect(text).toContain(`${detailsLabels.email}: ${subscriptionHistory[0].email}`); expect(text).toContain(`${detailsLabels.email}: ${subscription.email}`);
}); });
it('displays the correct value for the type cell', () => { it('displays the correct value for the type cell', () => {
const cellTestId = `subscription-cell-type`; const cellTestId = `subscription-cell-type`;
expect(findCellByTestid(cellTestId).text()).toBe(cloudLicenseText); const type =
subscription.type === subscriptionTypes.LICENSE_FILE ? licenseFileText : cloudLicenseText;
expect(findCellByTestid(cellTestId).text()).toBe(type);
}); });
it('displays the correct value for the plan cell', () => { it('displays the correct value for the plan cell', () => {
const cellTestId = `subscription-cell-plan`; const cellTestId = `subscription-cell-plan`;
expect(findCellByTestid(cellTestId).text()).toBe('Ultimate'); expect(findCellByTestid(cellTestId).text()).toBe(
capitalizeFirstCharacter(subscription.plan),
);
}); });
}); });
}); });
......
...@@ -35,7 +35,7 @@ export const license = { ...@@ -35,7 +35,7 @@ export const license = {
}, },
}; };
export const subscriptionHistory = [ export const subscriptionPastHistory = [
{ {
activatedAt: '2022-03-16', activatedAt: '2022-03-16',
company: 'ACME Corp', company: 'ACME Corp',
...@@ -62,6 +62,29 @@ export const subscriptionHistory = [ ...@@ -62,6 +62,29 @@ export const subscriptionHistory = [
}, },
]; ];
export const subscriptionFutureHistory = [
{
company: 'ACME Corp',
email: 'user@acmecorp.com',
expiresAt: '2023-03-16',
name: 'Jane Doe',
plan: 'ultimate',
startsAt: '2022-03-11',
type: subscriptionTypes.CLOUD,
usersInLicenseCount: '15',
},
{
company: 'ACME Corp',
email: 'user@acmecorp.com',
expiresAt: '2022-03-16',
name: 'Jane Doe',
plan: 'ultimate',
startsAt: '2021-03-16',
type: subscriptionTypes.CLOUD,
usersInLicenseCount: '10',
},
];
export const activateLicenseMutationResponse = { export const activateLicenseMutationResponse = {
FAILURE: [ FAILURE: [
{ {
......
...@@ -34954,7 +34954,10 @@ msgstr "" ...@@ -34954,7 +34954,10 @@ msgstr ""
msgid "SuperSonics|current subscription" msgid "SuperSonics|current subscription"
msgstr "" msgstr ""
msgid "SuperSonics|history subscriptions" msgid "SuperSonics|future subscriptions"
msgstr ""
msgid "SuperSonics|past subscriptions"
msgstr "" msgstr ""
msgid "Support" msgid "Support"
......
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