Commit 51bb42cb authored by Angelo Gulina's avatar Angelo Gulina Committed by Andrew Fontaine

Add remove button with confirmation

parent 2393b1eb
......@@ -8,6 +8,7 @@ import {
manageSubscriptionButtonText,
notificationType,
removeLicense,
removeLicenseConfirm,
subscriptionDetailsHeaderText,
subscriptionType,
syncSubscriptionButtonText,
......@@ -28,6 +29,7 @@ export default {
licensedToHeaderText,
manageSubscriptionButtonText,
removeLicense,
removeLicenseConfirm,
subscriptionDetailsHeaderText,
syncSubscriptionButtonText,
uploadLicense,
......@@ -47,7 +49,7 @@ export default {
SubscriptionDetailsUserInfo,
SubscriptionSyncNotifications: () => import('./subscription_sync_notifications.vue'),
},
inject: ['customersPortalUrl', 'licenseUploadPath', 'subscriptionSyncPath'],
inject: ['customersPortalUrl', 'licenseRemovePath', 'licenseUploadPath', 'subscriptionSyncPath'],
props: {
subscription: {
type: Object,
......@@ -77,7 +79,7 @@ export default {
return this.licenseUploadPath && this.isLegacyType;
},
canRemoveLicense() {
return false;
return this.licenseRemovePath && this.isLegacyType;
},
hasSubscription() {
return Boolean(Object.keys(this.subscription).length);
......@@ -172,6 +174,7 @@ export default {
category="secondary"
variant="confirm"
data-testid="license-upload-action"
data-qa-selector="license_upload_link"
>
{{ $options.i18n.uploadLicense }}
</gl-button>
......@@ -189,7 +192,11 @@ export default {
v-if="canRemoveLicense"
category="secondary"
variant="danger"
:href="licenseRemovePath"
:data-confirm="$options.i18n.removeLicenseConfirm"
data-method="delete"
data-testid="license-remove-action"
data-qa-selector="remove_license_link"
>
{{ $options.i18n.removeLicense }}
</gl-button>
......
......@@ -107,15 +107,20 @@ export default {
},
methods: {
cellClass(_, x, item) {
return item.id === this.currentSubscriptionId ? tdClassHighlight : tdClassBase;
return this.isCurrentSubscription(item) ? tdClassHighlight : tdClassBase;
},
rowAttr() {
isCurrentSubscription({ id }) {
return id === this.currentSubscriptionId;
},
rowAttr(item) {
return {
'data-testid': 'subscription-history-row',
'data-testid': this.isCurrentSubscription(item)
? 'subscription-current'
: 'subscription-history-row',
};
},
rowClass(item) {
return item.id === this.currentSubscriptionId ? 'gl-font-weight-bold gl-text-blue-500' : '';
return this.isCurrentSubscription(item) ? 'gl-font-weight-bold gl-text-blue-500' : '';
},
},
};
......
......@@ -38,6 +38,7 @@ export const detailsLabels = {
};
export const removeLicense = __('Remove license');
export const removeLicenseConfirm = __('Are you sure you want to remove the license?');
export const uploadLicense = __('Upload license');
export const uploadLegacyLicense = s__('SuperSonics|Upload a legacy license');
export const billableUsersTitle = s__('CloudLicense|Billable users');
......
......@@ -28,6 +28,7 @@ export default () => {
customersPortalUrl,
freeTrialPath,
hasActiveLicense,
licenseRemovePath,
licenseUploadPath,
subscriptionSyncPath,
} = el.dataset;
......@@ -43,6 +44,7 @@ export default () => {
connectivityHelpURL,
customersPortalUrl,
freeTrialPath,
licenseRemovePath,
licenseUploadPath,
subscriptionSyncPath,
},
......
......@@ -59,6 +59,7 @@ module LicenseHelper
free_trial_path: new_trial_url,
has_active_license: (has_active_license? ? 'true' : 'false'),
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path,
subscription_sync_path: sync_seat_link_admin_license_path
}
end
......
......@@ -11,36 +11,60 @@ RSpec.describe 'Admin views Cloud License', :js do
stub_application_setting(cloud_license_enabled: true)
end
context 'Cloud license' do
let_it_be(:license) { create_current_license(cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN) }
context 'with a cloud license' do
let!(:license) { create_current_license(cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN) }
before do
visit(admin_cloud_license_path)
end
context 'with a cloud license only' do
before do
visit(admin_cloud_license_path)
end
it 'displays the subscription details' do
page.within(find('#content-body', match: :first)) do
expect(page).to have_content('Subscription details')
expect(all("[data-testid='details-label']")[1]).to have_content('Plan:')
expect(all("[data-testid='details-content']")[1]).to have_content('Ultimate')
it 'displays the subscription details' do
page.within(find('#content-body', match: :first)) do
expect(page).to have_content('Subscription details')
expect(all("[data-testid='details-label']")[1]).to have_content('Plan:')
expect(all("[data-testid='details-content']")[1]).to have_content('Ultimate')
end
end
end
it 'succeeds to sync the subscription' do
page.within(find('#content-body', match: :first)) do
click_button('Sync subscription details')
it 'succeeds to sync the subscription' do
page.within(find('#content-body', match: :first)) do
click_button('Sync subscription details')
expect(page).to have_content('The subscription details synced successfully')
expect(page).to have_content('The subscription details synced successfully')
end
end
it 'fails to sync the subscription' do
create_current_license(cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN, expires_at: nil)
page.within(find('#content-body', match: :first)) do
click_button('Sync subscription details')
expect(page).to have_content('You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by troubleshooting the activation code')
end
end
end
end
it 'fails to sync the subscription' do
create_current_license(cloud_licensing_enabled: true, plan: License::ULTIMATE_PLAN, expires_at: nil)
context 'with a legacy license' do
let!(:license) { create_current_license(cloud_licensing_enabled: false, plan: License::ULTIMATE_PLAN) }
page.within(find('#content-body', match: :first)) do
click_button('Sync subscription details')
before do
visit(admin_cloud_license_path)
end
context 'when removing the a legacy license' do
before do
accept_alert do
click_on 'Remove license'
end
end
expect(page).to have_content('You can no longer sync your subscription details with GitLab. Get help for the most common connectivity issues by troubleshooting the activation code')
it 'shows a message saying the license was correctly removed' do
page.within(find('#content-body', match: :first)) do
expect(page).to have_content('The license was removed.')
end
end
end
end
......
......@@ -33,6 +33,7 @@ describe('Subscription Breakdown', () => {
const [, legacyLicense] = subscriptionHistory;
const connectivityHelpURL = 'connectivity/help/url';
const customersPortalUrl = 'customers.dot';
const licenseRemovePath = '/license/remove/';
const licenseUploadPath = '/license/upload/';
const subscriptionSyncPath = '/sync/path/';
......@@ -41,6 +42,7 @@ describe('Subscription Breakdown', () => {
const findDetailsHistory = () => wrapper.findComponent(SubscriptionDetailsHistory);
const findDetailsUserInfo = () => wrapper.findComponent(SubscriptionDetailsUserInfo);
const findLicenseUploadAction = () => wrapper.findByTestId('license-upload-action');
const findLicenseRemoveAction = () => wrapper.findByTestId('license-remove-action');
const findSubscriptionActivationAction = () =>
wrapper.findByTestId('subscription-activation-action');
const findSubscriptionMangeAction = () => wrapper.findByTestId('subscription-manage-action');
......@@ -64,6 +66,7 @@ describe('Subscription Breakdown', () => {
connectivityHelpURL,
customersPortalUrl,
licenseUploadPath,
licenseRemovePath,
subscriptionSyncPath,
...provide,
},
......@@ -154,7 +157,7 @@ describe('Subscription Breakdown', () => {
${undefined} | ${subscriptionType.CLOUD} | ${false}
${undefined} | ${subscriptionType.LEGACY} | ${false}
`(
'with url is $url and type is $type the sync buttons is shown: $shouldShow',
'with url is $url and type is $type the sync button is shown: $shouldShow',
({ url, type, shouldShow }) => {
const provide = { subscriptionSyncPath: url };
const props = { subscription: { ...license.ULTIMATE, type } };
......@@ -174,7 +177,7 @@ describe('Subscription Breakdown', () => {
${undefined} | ${subscriptionType.LEGACY} | ${false}
${undefined} | ${subscriptionType.CLOUD} | ${false}
`(
'with url is $url and type is $type the upload buttons is shown: $shouldShow',
'with url is $url and type is $type the upload button is shown: $shouldShow',
({ url, type, shouldShow }) => {
const provide = { licenseUploadPath: url };
const props = { subscription: { ...license.ULTIMATE, type } };
......@@ -190,7 +193,7 @@ describe('Subscription Breakdown', () => {
${customersPortalUrl} | ${true}
${''} | ${false}
${undefined} | ${false}
`('with url is $url the manage buttons is shown: $shouldShow', ({ url, shouldShow }) => {
`('with url is $url the manage button is shown: $shouldShow', ({ url, shouldShow }) => {
const provide = { customersPortalUrl: url };
const stubs = { GlCard, SubscriptionDetailsCard };
createComponent({ provide, stubs });
......@@ -198,7 +201,25 @@ describe('Subscription Breakdown', () => {
expect(findSubscriptionMangeAction().exists()).toBe(shouldShow);
});
it.todo('should show a remove subscription button');
it.each`
url | type | shouldShow
${licenseRemovePath} | ${subscriptionType.LEGACY} | ${true}
${licenseRemovePath} | ${subscriptionType.CLOUD} | ${false}
${''} | ${subscriptionType.LEGACY} | ${false}
${''} | ${subscriptionType.CLOUD} | ${false}
${undefined} | ${subscriptionType.LEGACY} | ${false}
${undefined} | ${subscriptionType.CLOUD} | ${false}
`(
'with url is $url and type is $type the remove button is shown: $shouldShow',
({ url, type, shouldShow }) => {
const provide = { licenseRemovePath: url };
const props = { subscription: { ...license.ULTIMATE, type } };
const stubs = { GlCard, SubscriptionDetailsCard };
createComponent({ props, provide, stubs });
expect(findLicenseRemoveAction().exists()).toBe(shouldShow);
},
);
});
describe('with a legacy license', () => {
......
......@@ -7,6 +7,7 @@ import { license, subscriptionHistory } from '../mock_data';
describe('Subscription Details History', () => {
let wrapper;
const findCurrentRow = () => wrapper.findByTestId('subscription-current');
const findTableRows = () => wrapper.findAllByTestId('subscription-history-row');
const cellFinder = (row) => (testId) => extendedWrapper(row).findByTestId(testId);
const containsABadge = (row) => row.findComponent(GlBadge).exists();
......@@ -32,13 +33,17 @@ describe('Subscription Details History', () => {
createComponent();
});
it('has the correct number of rows', () => {
expect(findTableRows()).toHaveLength(2);
it('has a current subscription row', () => {
expect(findCurrentRow().exists()).toBe(true);
});
it('has the correct number of subscription rows', () => {
expect(findTableRows()).toHaveLength(1);
});
it('has the correct license type', () => {
expect(findTableRows().at(0).text()).toContain('Cloud License');
expect(findTableRows().at(1).text()).toContain('Legacy License');
expect(findCurrentRow().text()).toContain('Cloud License');
expect(findTableRows().at(0).text()).toContain('Legacy License');
});
it('has a badge for the license type', () => {
......@@ -46,11 +51,11 @@ describe('Subscription Details History', () => {
});
it('highlights the current subscription row', () => {
expect(findTableRows().at(0).classes('gl-text-blue-500')).toBe(true);
expect(findCurrentRow().classes('gl-text-blue-500')).toBe(true);
});
it('does not highlight the current subscription row', () => {
expect(findTableRows().at(1).classes('gl-text-blue-500')).toBe(false);
it('does not highlight the other subscription row', () => {
expect(findTableRows().at(0).classes('gl-text-blue-500')).toBe(false);
});
describe('cell data', () => {
......@@ -58,7 +63,7 @@ describe('Subscription Details History', () => {
beforeEach(() => {
createComponent();
findCellByTestid = cellFinder(findTableRows().at(0));
findCellByTestid = cellFinder(findCurrentRow());
});
it.each`
......
......@@ -98,7 +98,8 @@ RSpec.describe LicenseHelper do
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url',
subscription_sync_path: sync_seat_link_admin_license_path,
license_upload_path: new_admin_license_path })
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path })
end
end
......@@ -111,7 +112,8 @@ RSpec.describe LicenseHelper do
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url',
subscription_sync_path: sync_seat_link_admin_license_path,
license_upload_path: new_admin_license_path })
license_upload_path: new_admin_license_path,
license_remove_path: admin_license_path })
end
end
end
......
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