Commit 6b749b34 authored by Stan Hu's avatar Stan Hu

Refresh shared runner state when credit card is validated

Once validated, this enables a user that disabled shared runners to
enable them again.
parent 1ac97dcf
...@@ -36,13 +36,17 @@ export default { ...@@ -36,13 +36,17 @@ export default {
isLoading: false, isLoading: false,
isSharedRunnerEnabled: false, isSharedRunnerEnabled: false,
errorMessage: null, errorMessage: null,
isCcValidationRequired: false,
}; };
}, },
created() { created() {
this.isSharedRunnerEnabled = this.isEnabled; this.isSharedRunnerEnabled = this.isEnabled;
this.ccValidationRequired = this.isCreditCardValidationRequired; this.isCcValidationRequired = this.isCreditCardValidationRequired;
}, },
methods: { methods: {
creditCardValidated() {
this.isCcValidationRequired = false;
},
toggleSharedRunners() { toggleSharedRunners() {
this.isLoading = true; this.isLoading = true;
this.errorMessage = null; this.errorMessage = null;
...@@ -52,7 +56,7 @@ export default { ...@@ -52,7 +56,7 @@ export default {
.then(() => { .then(() => {
this.isLoading = false; this.isLoading = false;
this.isSharedRunnerEnabled = !this.isSharedRunnerEnabled; this.isSharedRunnerEnabled = !this.isSharedRunnerEnabled;
this.ccValidationRequired = this.isCreditCardValidationRequired; this.isCcValidationRequired = this.isCreditCardValidationRequired;
}) })
.catch((error) => { .catch((error) => {
this.isLoading = false; this.isLoading = false;
...@@ -70,8 +74,8 @@ export default { ...@@ -70,8 +74,8 @@ export default {
{{ errorMessage }} {{ errorMessage }}
</gl-alert> </gl-alert>
<div v-if="this.isCreditCardValidationRequired && !this.isSharedRunnerEnabled"> <div v-if="isCcValidationRequired && !isSharedRunnerEnabled">
<cc-validation-required-alert class="gl-pb-5" /> <cc-validation-required-alert class="gl-pb-5" @verifiedCreditCard="creditCardValidated" />
</div> </div>
<div v-else ref="sharedRunnersToggle"> <div v-else ref="sharedRunnersToggle">
<gl-toggle <gl-toggle
......
...@@ -4,7 +4,12 @@ import SharedRunnersToggle from '~/projects/settings/components/shared_runners_t ...@@ -4,7 +4,12 @@ import SharedRunnersToggle from '~/projects/settings/components/shared_runners_t
export default (containerId = 'toggle-shared-runners-form') => { export default (containerId = 'toggle-shared-runners-form') => {
const containerEl = document.getElementById(containerId); const containerEl = document.getElementById(containerId);
const { isDisabledAndUnoverridable, isEnabled, updatePath, isCreditCardValidationRequired } = containerEl.dataset; const {
isDisabledAndUnoverridable,
isEnabled,
updatePath,
isCreditCardValidationRequired,
} = containerEl.dataset;
return new Vue({ return new Vue({
el: containerEl, el: containerEl,
......
...@@ -48,6 +48,7 @@ export default { ...@@ -48,6 +48,7 @@ export default {
handleSuccessfulVerification() { handleSuccessfulVerification() {
this.$refs.modal.hide(); this.$refs.modal.hide();
this.shouldRenderSuccess = true; this.shouldRenderSuccess = true;
this.$emit('verifiedCreditCard');
}, },
}, },
i18n, i18n,
......
...@@ -9,7 +9,11 @@ module EE ...@@ -9,7 +9,11 @@ module EE
override :toggle_shared_runners_settings_data override :toggle_shared_runners_settings_data
def toggle_shared_runners_settings_data(project) def toggle_shared_runners_settings_data(project)
super.merge(is_credit_card_validation_required: "#{!current_user&.has_required_credit_card_to_enable_shared_runners?(project)}") super.merge(is_credit_card_validation_required: "#{validate_credit_card?(project)}")
end
def validate_credit_card?(project)
!current_user.has_required_credit_card_to_enable_shared_runners?(project)
end end
def show_buy_pipeline_minutes?(project, namespace) def show_buy_pipeline_minutes?(project, namespace)
......
import { GlAlert, GlSprintf } from '@gitlab/ui'; import { GlAlert, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import AccountVerificationModal from 'ee/billings/components/account_verification_modal.vue';
import CreditCardValidationRequiredAlert from 'ee/billings/components/cc_validation_required_alert.vue'; import CreditCardValidationRequiredAlert from 'ee/billings/components/cc_validation_required_alert.vue';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
...@@ -26,6 +27,7 @@ describe('CreditCardValidationRequiredAlert', () => { ...@@ -26,6 +27,7 @@ describe('CreditCardValidationRequiredAlert', () => {
}; };
wrapper = createComponent(); wrapper = createComponent();
wrapper.vm.$refs.modal.hide = jest.fn();
}); });
afterEach(() => { afterEach(() => {
...@@ -49,4 +51,11 @@ describe('CreditCardValidationRequiredAlert', () => { ...@@ -49,4 +51,11 @@ describe('CreditCardValidationRequiredAlert', () => {
expect(findGlAlert().attributes('variant')).toBe('success'); expect(findGlAlert().attributes('variant')).toBe('success');
}); });
it('hides the modal and emits a verifiedCreditCard event upon success', () => {
wrapper.findComponent(AccountVerificationModal).vm.$emit('success');
expect(wrapper.vm.$refs.modal.hide).toHaveBeenCalled();
expect(wrapper.emitted('verifiedCreditCard')).toBeDefined();
});
}); });
...@@ -81,6 +81,30 @@ RSpec.describe EE::Ci::RunnersHelper do ...@@ -81,6 +81,30 @@ RSpec.describe EE::Ci::RunnersHelper do
end end
end end
describe '#toggle_shared_runners_settings_data' do
let(:valid_card) { true }
subject { helper.toggle_shared_runners_settings_data(project) }
before do
expect(user).to receive(:has_required_credit_card_to_enable_shared_runners?).with(project).and_return(valid_card)
end
context 'when user has a valid credit card' do
it 'return is_credit_card_validation_required as "false"' do
expect(subject[:is_credit_card_validation_required]).to eq('false')
end
end
context 'when user does not have a valid credit card' do
let(:valid_card) { false }
it 'return is_credit_card_validation_required as "true"' do
expect(subject[:is_credit_card_validation_required]).to eq('true')
end
end
end
context 'with notifications' do context 'with notifications' do
let(:dev_env_or_com) { true } let(:dev_env_or_com) { true }
......
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui'; import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter'; import MockAxiosAdapter from 'axios-mock-adapter';
import CcValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue';
import { TEST_HOST } from 'helpers/test_constants';
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 SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue'; import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
...@@ -20,6 +22,7 @@ describe('projects/settings/components/shared_runners', () => { ...@@ -20,6 +22,7 @@ describe('projects/settings/components/shared_runners', () => {
isDisabledAndUnoverridable: false, isDisabledAndUnoverridable: false,
isLoading: false, isLoading: false,
updatePath: TEST_UPDATE_PATH, updatePath: TEST_UPDATE_PATH,
isCreditCardValidationRequired: false,
...props, ...props,
}, },
}); });
...@@ -28,6 +31,7 @@ describe('projects/settings/components/shared_runners', () => { ...@@ -28,6 +31,7 @@ describe('projects/settings/components/shared_runners', () => {
const findErrorAlert = () => wrapper.find(GlAlert); const findErrorAlert = () => wrapper.find(GlAlert);
const findSharedRunnersToggle = () => wrapper.find(GlToggle); const findSharedRunnersToggle = () => wrapper.find(GlToggle);
const findToggleTooltip = () => wrapper.find(GlTooltip); const findToggleTooltip = () => wrapper.find(GlTooltip);
const findCcValidationRequiredAlert = () => wrapper.find(CcValidationRequiredAlert);
const getToggleValue = () => findSharedRunnersToggle().props('value'); const getToggleValue = () => findSharedRunnersToggle().props('value');
const isToggleLoading = () => findSharedRunnersToggle().props('isLoading'); const isToggleLoading = () => findSharedRunnersToggle().props('isLoading');
const isToggleDisabled = () => findSharedRunnersToggle().props('disabled'); const isToggleDisabled = () => findSharedRunnersToggle().props('disabled');
...@@ -154,4 +158,37 @@ describe('projects/settings/components/shared_runners', () => { ...@@ -154,4 +158,37 @@ describe('projects/settings/components/shared_runners', () => {
}); });
}); });
}); });
describe('with credit card validation required and shared runners DISABLED', () => {
beforeEach(() => {
window.gon = {
subscriptions_url: TEST_HOST,
payment_form_url: TEST_HOST,
};
createComponent({
isCreditCardValidationRequired: true,
isEnabled: false,
});
});
it('toggle should not be visible', () => {
expect(findSharedRunnersToggle().exists()).toBe(false);
});
it('credit card validation component should exist', () => {
expect(findCcValidationRequiredAlert().exists()).toBe(true);
});
describe('when credit card is validated', () => {
it('should show the toggle button', async () => {
findCcValidationRequiredAlert().vm.$emit('verifiedCreditCard');
await waitForPromises();
expect(findSharedRunnersToggle().exists()).toBe(true);
expect(getToggleValue()).toBe(false);
expect(isToggleDisabled()).toBe(false);
});
});
});
}); });
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Ci::RunnersHelper do RSpec.describe Ci::RunnersHelper do
let_it_be(:user, refind: true) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(user)
end
describe '#runner_status_icon', :clean_gitlab_redis_cache do describe '#runner_status_icon', :clean_gitlab_redis_cache do
it "returns - not contacted yet" do it "returns - not contacted yet" do
runner = create(:ci_runner) runner = create(:ci_runner)
...@@ -90,28 +96,28 @@ RSpec.describe Ci::RunnersHelper do ...@@ -90,28 +96,28 @@ RSpec.describe Ci::RunnersHelper do
context 'when project has runners' do context 'when project has runners' do
it 'returns the correct value for is_enabled' do it 'returns the correct value for is_enabled' do
data = toggle_shared_runners_settings_data(project_with_runners) data = helper.toggle_shared_runners_settings_data(project_with_runners)
expect(data[:is_enabled]).to eq("true") expect(data[:is_enabled]).to eq("true")
end end
end end
context 'when project does not have runners' do context 'when project does not have runners' do
it 'returns the correct value for is_enabled' do it 'returns the correct value for is_enabled' do
data = toggle_shared_runners_settings_data(project_without_runners) data = helper.toggle_shared_runners_settings_data(project_without_runners)
expect(data[:is_enabled]).to eq("false") expect(data[:is_enabled]).to eq("false")
end end
end end
context 'for all projects' do context 'for all projects' do
it 'returns the update path for toggling the shared runners setting' do it 'returns the update path for toggling the shared runners setting' do
data = toggle_shared_runners_settings_data(project_with_runners) data = helper.toggle_shared_runners_settings_data(project_with_runners)
expect(data[:update_path]).to eq(toggle_shared_runners_project_runners_path(project_with_runners)) expect(data[:update_path]).to eq(toggle_shared_runners_project_runners_path(project_with_runners))
end end
it 'returns false for is_disabled_and_unoverridable when project has no group' do it 'returns false for is_disabled_and_unoverridable when project has no group' do
project = create(:project) project = create(:project)
data = toggle_shared_runners_settings_data(project) data = helper.toggle_shared_runners_settings_data(project)
expect(data[:is_disabled_and_unoverridable]).to eq("false") expect(data[:is_disabled_and_unoverridable]).to eq("false")
end end
...@@ -129,7 +135,7 @@ RSpec.describe Ci::RunnersHelper do ...@@ -129,7 +135,7 @@ RSpec.describe Ci::RunnersHelper do
project = create(:project, group: group) project = create(:project, group: group)
allow(group).to receive(:shared_runners_setting).and_return(shared_runners_setting) allow(group).to receive(:shared_runners_setting).and_return(shared_runners_setting)
data = toggle_shared_runners_settings_data(project) data = helper.toggle_shared_runners_settings_data(project)
expect(data[:is_disabled_and_unoverridable]).to eq(is_disabled_and_unoverridable) expect(data[:is_disabled_and_unoverridable]).to eq(is_disabled_and_unoverridable)
end 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