Commit 9f6e4149 authored by Doug Stull's avatar Doug Stull

Reuse the country and state selector for hand raise leads

- DRY up code and logic
parent e5435114
...@@ -29,7 +29,6 @@ RSpec/AnyInstanceOf: ...@@ -29,7 +29,6 @@ RSpec/AnyInstanceOf:
- ee/spec/features/security/project/internal_access_spec.rb - ee/spec/features/security/project/internal_access_spec.rb
- ee/spec/features/security/project/private_access_spec.rb - ee/spec/features/security/project/private_access_spec.rb
- ee/spec/features/security/project/public_access_spec.rb - ee/spec/features/security/project/public_access_spec.rb
- ee/spec/features/trials/capture_lead_spec.rb
- ee/spec/features/trials/select_namespace_spec.rb - ee/spec/features/trials/select_namespace_spec.rb
- ee/spec/features/users/login_spec.rb - ee/spec/features/users/login_spec.rb
- ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb - ee/spec/graphql/mutations/dast_on_demand_scans/create_spec.rb
......
...@@ -14,9 +14,8 @@ import { sprintf } from '~/locale'; ...@@ -14,9 +14,8 @@ import { sprintf } from '~/locale';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import countriesQuery from 'ee/subscriptions/graphql/queries/countries.query.graphql'; import countriesQuery from 'ee/subscriptions/graphql/queries/countries.query.graphql';
import statesQuery from 'ee/subscriptions/graphql/queries/states.query.graphql'; import statesQuery from 'ee/subscriptions/graphql/queries/states.query.graphql';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; import CountryOrRegionSelector from 'ee/trials/components/country_or_region_selector.vue';
import { import {
COUNTRIES_WITH_STATES_ALLOWED,
LEADS_COMPANY_NAME_LABEL, LEADS_COMPANY_NAME_LABEL,
LEADS_COMPANY_SIZE_LABEL, LEADS_COMPANY_SIZE_LABEL,
LEADS_COUNTRY_LABEL, LEADS_COUNTRY_LABEL,
...@@ -51,10 +50,10 @@ export default { ...@@ -51,10 +50,10 @@ export default {
GlFormSelect, GlFormSelect,
GlFormTextarea, GlFormTextarea,
GlModal, GlModal,
CountryOrRegionSelector,
}, },
directives: { directives: {
GlModal: GlModalDirective, GlModal: GlModalDirective,
autofocusonshow,
}, },
mixins: [Tracking.mixin()], mixins: [Tracking.mixin()],
inject: ['user', 'small'], inject: ['user', 'small'],
...@@ -66,11 +65,12 @@ export default { ...@@ -66,11 +65,12 @@ export default {
companyName: this.user.companyName, companyName: this.user.companyName,
companySize: null, companySize: null,
phoneNumber: '', phoneNumber: '',
country: null, country: '',
state: null, state: '',
countries: [], countries: [],
states: [], states: [],
comment: '', comment: '',
stateRequired: false,
}; };
}, },
apollo: { apollo: {
...@@ -95,9 +95,6 @@ export default { ...@@ -95,9 +95,6 @@ export default {
userName: this.user.userName, userName: this.user.userName,
}); });
}, },
mustEnterState() {
return COUNTRIES_WITH_STATES_ALLOWED.includes(this.country);
},
canSubmit() { canSubmit() {
return ( return (
this.firstName && this.firstName &&
...@@ -106,7 +103,7 @@ export default { ...@@ -106,7 +103,7 @@ export default {
this.companySize && this.companySize &&
this.phoneNumber && this.phoneNumber &&
this.country && this.country &&
(this.mustEnterState ? this.state : true) (this.stateRequired ? this.state : true)
); );
}, },
actionPrimary() { actionPrimary() {
...@@ -125,9 +122,6 @@ export default { ...@@ -125,9 +122,6 @@ export default {
label: 'hand_raise_lead_form', label: 'hand_raise_lead_form',
}; };
}, },
showState() {
return !this.$apollo.loading.states && this.states && this.country && this.mustEnterState;
},
companySizeOptionsWithDefault() { companySizeOptionsWithDefault() {
return [ return [
{ {
...@@ -137,24 +131,6 @@ export default { ...@@ -137,24 +131,6 @@ export default {
...companySizes, ...companySizes,
]; ];
}, },
countryOptionsWithDefault() {
return [
{
name: this.$options.i18n.countrySelectPrompt,
id: null,
},
...this.countries,
];
},
stateOptionsWithDefault() {
return [
{
name: this.$options.i18n.stateSelectPrompt,
id: null,
},
...this.states,
];
},
formParams() { formParams() {
return { return {
namespaceId: Number(this.user.namespaceId), namespaceId: Number(this.user.namespaceId),
...@@ -164,7 +140,7 @@ export default { ...@@ -164,7 +140,7 @@ export default {
companySize: this.companySize, companySize: this.companySize,
phoneNumber: this.phoneNumber, phoneNumber: this.phoneNumber,
country: this.country, country: this.country,
state: this.mustEnterState ? this.state : null, state: this.stateRequired ? this.state : null,
comment: this.comment, comment: this.comment,
glmContent: this.user.glmContent, glmContent: this.user.glmContent,
}; };
...@@ -177,9 +153,10 @@ export default { ...@@ -177,9 +153,10 @@ export default {
this.companyName = ''; this.companyName = '';
this.companySize = null; this.companySize = null;
this.phoneNumber = ''; this.phoneNumber = '';
this.country = null; this.country = '';
this.state = null; this.state = '';
this.comment = ''; this.comment = '';
this.stateRequired = false;
}, },
async submit() { async submit() {
this.isLoading = true; this.isLoading = true;
...@@ -205,6 +182,11 @@ export default { ...@@ -205,6 +182,11 @@ export default {
this.isLoading = false; this.isLoading = false;
}); });
}, },
onChange({ country, state, stateRequired }) {
this.country = country;
this.state = state;
this.stateRequired = stateRequired;
},
}, },
i18n: { i18n: {
firstNameLabel: LEADS_FIRST_NAME_LABEL, firstNameLabel: LEADS_FIRST_NAME_LABEL,
...@@ -247,6 +229,7 @@ export default { ...@@ -247,6 +229,7 @@ export default {
<gl-modal <gl-modal
ref="modal" ref="modal"
modal-id="hand-raise-lead" modal-id="hand-raise-lead"
data-testid="hand-raise-lead-modal"
size="sm" size="sm"
:title="$options.i18n.modalTitle" :title="$options.i18n.modalTitle"
:action-primary="actionPrimary" :action-primary="actionPrimary"
...@@ -309,7 +292,7 @@ export default { ...@@ -309,7 +292,7 @@ export default {
> >
<gl-form-select <gl-form-select
v-model="companySize" v-model="companySize"
v-autofocusonshow name="company-size"
:options="companySizeOptionsWithDefault" :options="companySizeOptionsWithDefault"
value-field="id" value-field="id"
text-field="name" text-field="name"
...@@ -331,37 +314,7 @@ export default { ...@@ -331,37 +314,7 @@ export default {
data-testid="phone-number" data-testid="phone-number"
/> />
</gl-form-group> </gl-form-group>
<gl-form-group <country-or-region-selector :country="country" :state="state" @change="onChange" />
v-if="!$apollo.loading.countries"
:label="$options.i18n.countryLabel"
label-size="sm"
label-for="country"
>
<gl-form-select
v-model="country"
v-autofocusonshow
:options="countryOptionsWithDefault"
value-field="id"
text-field="name"
data-testid="country"
/>
</gl-form-group>
<gl-form-group
v-if="showState"
:label="$options.i18n.stateLabel"
label-size="sm"
label-for="state"
>
<gl-form-select
v-model="state"
v-autofocusonshow
:options="stateOptionsWithDefault"
value-field="id"
text-field="name"
data-testid="state"
/>
</gl-form-group>
<gl-form-group :label="$options.i18n.commentLabel" label-size="sm" label-for="comment"> <gl-form-group :label="$options.i18n.commentLabel" label-size="sm" label-for="comment">
<gl-form-textarea v-model="comment" /> <gl-form-textarea v-model="comment" />
</gl-form-group> </gl-form-group>
......
...@@ -19,9 +19,23 @@ export default { ...@@ -19,9 +19,23 @@ export default {
directives: { directives: {
autofocusonshow, autofocusonshow,
}, },
inject: ['user'], props: {
country: {
type: String,
required: true,
},
state: {
type: String,
required: true,
},
required: {
type: Boolean,
default: false,
required: false,
},
},
data() { data() {
return { ...this.user, countries: [], states: [] }; return { selectedCountry: this.country, selectedState: this.state, countries: [], states: [] };
}, },
i18n: { i18n: {
countryLabel: LEADS_COUNTRY_LABEL, countryLabel: LEADS_COUNTRY_LABEL,
...@@ -34,27 +48,45 @@ export default { ...@@ -34,27 +48,45 @@ export default {
return [ return [
{ {
name: this.$options.i18n.countrySelectPrompt, name: this.$options.i18n.countrySelectPrompt,
id: null, id: '',
}, },
...this.countries, ...this.countries,
]; ];
}, },
mustEnterState() { stateRequired() {
return COUNTRIES_WITH_STATES_ALLOWED.includes(this.country); return COUNTRIES_WITH_STATES_ALLOWED.includes(this.selectedCountry);
}, },
showState() { showState() {
return !this.$apollo.loading.states && this.states && this.country && this.mustEnterState; return (
!this.$apollo.loading.states && this.states && this.selectedCountry && this.stateRequired
);
}, },
stateOptionsWithDefault() { stateOptionsWithDefault() {
return [ return [
{ {
name: this.$options.i18n.stateSelectPrompt, name: this.$options.i18n.stateSelectPrompt,
id: null, id: '',
}, },
...this.states, ...this.states,
]; ];
}, },
}, },
methods: {
selected() {
this.setSelectedState();
this.$emit('change', {
country: this.selectedCountry,
state: this.selectedState,
stateRequired: this.stateRequired,
});
},
setSelectedState() {
if (!this.showState) {
this.selectedState = '';
}
},
},
apollo: { apollo: {
countries: { countries: {
query: countriesQuery, query: countriesQuery,
...@@ -62,11 +94,11 @@ export default { ...@@ -62,11 +94,11 @@ export default {
states: { states: {
query: statesQuery, query: statesQuery,
skip() { skip() {
return !this.country; return !this.selectedCountry;
}, },
variables() { variables() {
return { return {
countryId: this.country, countryId: this.selectedCountry,
}; };
}, },
}, },
...@@ -84,14 +116,15 @@ export default { ...@@ -84,14 +116,15 @@ export default {
> >
<gl-form-select <gl-form-select
id="country" id="country"
v-model="country" v-model="selectedCountry"
name="country" name="country"
:options="countryOptionsWithDefault" :options="countryOptionsWithDefault"
value-field="id" value-field="id"
text-field="name" text-field="name"
data-qa-selector="country" data-qa-selector="country"
data-testid="country" data-testid="country"
required :required="required"
@change="selected"
/> />
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group
...@@ -102,14 +135,15 @@ export default { ...@@ -102,14 +135,15 @@ export default {
> >
<gl-form-select <gl-form-select
id="state" id="state"
v-model="selectedState"
v-autofocusonshow v-autofocusonshow
:value="state"
name="state" name="state"
:options="stateOptionsWithDefault" :options="stateOptionsWithDefault"
value-field="id" value-field="id"
text-field="name" text-field="name"
data-testid="state" data-testid="state"
required :required="required"
@change="selected"
/> />
</gl-form-group> </gl-form-group>
</div> </div>
......
...@@ -123,7 +123,7 @@ export default { ...@@ -123,7 +123,7 @@ export default {
required required
/> />
</gl-form-group> </gl-form-group>
<country-or-region-selector /> <country-or-region-selector :country="country" :state="state" required />
<gl-form-group <gl-form-group
:label="$options.i18n.phoneNumberLabel" :label="$options.i18n.phoneNumberLabel"
label-size="sm" label-size="sm"
......
...@@ -25,8 +25,8 @@ export const initTrialCreateLeadForm = () => { ...@@ -25,8 +25,8 @@ export const initTrialCreateLeadForm = () => {
lastName, lastName,
companyName, companyName,
companySize: companySize || null, companySize: companySize || null,
country: country || null, country: country || '',
state: state || null, state: state || '',
phoneNumber, phoneNumber,
}, },
submitPath, submitPath,
......
...@@ -70,13 +70,56 @@ RSpec.describe 'Billing plan pages', :feature, :js do ...@@ -70,13 +70,56 @@ RSpec.describe 'Billing plan pages', :feature, :js do
it 'displays the in-app hand raise lead', :aggregate_failures do it 'displays the in-app hand raise lead', :aggregate_failures do
if namespace.group_namespace? if namespace.group_namespace?
form_data = {
first_name: user.first_name,
last_name: user.last_name,
phone_number: '+1 23 456-78-90',
company_size: '1 - 99',
company_name: user.organization,
country: { id: 'US', name: 'United States of America' },
state: { id: 'CA', name: 'California' }
}
hand_raise_lead_params = {
"first_name" => form_data[:first_name],
"last_name" => form_data[:last_name],
"company_name" => form_data[:company_name],
"company_size" => form_data[:company_size].delete(' '),
"phone_number" => form_data[:phone_number],
"country" => form_data.dig(:country, :id),
"state" => form_data.dig(:state, :id),
"namespace_id" => namespace.id,
"comment" => '',
"glm_content" => 'billing-group',
"work_email" => user.email,
"uid" => user.id,
"setup_for_company" => user.setup_for_company,
"provider" => "gitlab",
"glm_source" => 'gitlab.com'
}
lead_params = ActionController::Parameters.new(hand_raise_lead_params).permit!
expect_next_instance_of(GitlabSubscriptions::CreateHandRaiseLeadService) do |service|
expect(service).to receive(:execute).with(lead_params).and_return(double('lead', success?: true ))
end
page.within('[data-testid="plan-card-premium"]') do page.within('[data-testid="plan-card-premium"]') do
click_button 'Contact sales' click_button 'Contact sales'
end end
expect(page).to have_content('Contact our Sales team') expect(page).to have_content('Contact our Sales team')
expect(page).to have_field('First Name', with: 'James') expect(page).to have_field('First Name', with: form_data[:first_name])
expect(page).to have_field('Last Name', with: 'Bond') expect(page).to have_field('Last Name', with: form_data[:last_name])
expect(page).to have_field('Company Name', with: 'ACME') expect(page).to have_field('Company Name', with: form_data[:company_name])
page.within('[data-testid="hand-raise-lead-modal"]') do
select form_data[:company_size], from: 'company-size'
fill_in 'phone-number', with: form_data[:phone_number]
select form_data.dig(:country, :name), from: 'country'
select form_data.dig(:state, :name), from: 'state'
click_button 'Submit information'
end
else else
expect(page).to have_selector(".js-hand-raise-lead-button[data-namespace-id='#{namespace.id}'][data-user-name='#{user.username}']", visible: false) expect(page).to have_selector(".js-hand-raise-lead-button[data-namespace-id='#{namespace.id}'][data-user-name='#{user.username}']", visible: false)
end end
......
...@@ -47,8 +47,8 @@ RSpec.describe 'Trial Capture Lead', :js do ...@@ -47,8 +47,8 @@ RSpec.describe 'Trial Capture Lead', :js do
trial_user: ActionController::Parameters.new(trial_user_params).permit! trial_user: ActionController::Parameters.new(trial_user_params).permit!
} }
expect_any_instance_of(GitlabSubscriptions::CreateLeadService).to receive(:execute).with(lead_params) do expect_next_instance_of(GitlabSubscriptions::CreateLeadService) do |service|
{ success: true } expect(service).to receive(:execute).with(lead_params).and_return({ success: true })
end end
end end
......
...@@ -3,7 +3,6 @@ import Vue, { nextTick } from 'vue'; ...@@ -3,7 +3,6 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { sprintf } from '~/locale'; import { sprintf } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking } from 'helpers/tracking_helper'; import { mockTracking } from 'helpers/tracking_helper';
import HandRaiseLeadButton from 'ee/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue'; import HandRaiseLeadButton from 'ee/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue';
import { import {
...@@ -14,30 +13,16 @@ import { ...@@ -14,30 +13,16 @@ import {
PQL_MODAL_FOOTER_TEXT, PQL_MODAL_FOOTER_TEXT,
} from 'ee/hand_raise_leads/hand_raise_lead/constants'; } from 'ee/hand_raise_leads/hand_raise_lead/constants';
import * as SubscriptionsApi from 'ee/api/subscriptions_api'; import * as SubscriptionsApi from 'ee/api/subscriptions_api';
import { formData, states, countries } from './mock_data'; import { FORM_DATA } from './mock_data';
Vue.use(VueApollo); Vue.use(VueApollo);
describe('HandRaiseLeadButton', () => { describe('HandRaiseLeadButton', () => {
let wrapper; let wrapper;
let fakeApollo;
let trackingSpy; let trackingSpy;
const createComponent = (small = false) => { const createComponent = (small = false) => {
const mockResolvers = {
Query: {
countries() {
return [{ id: 'US', name: 'United States' }];
},
states() {
return [{ countryId: 'US', id: 'CA', name: 'California' }];
},
},
};
fakeApollo = createMockApollo([], mockResolvers);
return shallowMountExtended(HandRaiseLeadButton, { return shallowMountExtended(HandRaiseLeadButton, {
apolloProvider: fakeApollo,
provide: { provide: {
small, small,
user: { user: {
...@@ -59,7 +44,6 @@ describe('HandRaiseLeadButton', () => { ...@@ -59,7 +44,6 @@ describe('HandRaiseLeadButton', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
fakeApollo = null;
}); });
describe('rendering', () => { describe('rendering', () => {
...@@ -87,7 +71,6 @@ describe('HandRaiseLeadButton', () => { ...@@ -87,7 +71,6 @@ describe('HandRaiseLeadButton', () => {
{ id: 'company-name', value: 'ACME' }, { id: 'company-name', value: 'ACME' },
{ id: 'phone-number', value: '' }, { id: 'phone-number', value: '' },
{ id: 'company-size', value: undefined }, { id: 'company-size', value: undefined },
{ id: 'country', value: undefined },
]; ];
formInputValues.forEach(({ id, value }) => { formInputValues.forEach(({ id, value }) => {
...@@ -104,7 +87,6 @@ describe('HandRaiseLeadButton', () => { ...@@ -104,7 +87,6 @@ describe('HandRaiseLeadButton', () => {
'company-name', 'company-name',
'company-size', 'company-size',
'phone-number', 'phone-number',
'country',
]; ];
visibleFields.forEach((f) => expect(wrapper.findByTestId(f).exists()).toBe(true)); visibleFields.forEach((f) => expect(wrapper.findByTestId(f).exists()).toBe(true));
...@@ -155,7 +137,7 @@ describe('HandRaiseLeadButton', () => { ...@@ -155,7 +137,7 @@ describe('HandRaiseLeadButton', () => {
it('becomes enabled when required info is there', async () => { it('becomes enabled when required info is there', async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
wrapper.setData({ countries, states, ...formData }); wrapper.setData({ ...FORM_DATA });
await nextTick(); await nextTick();
...@@ -166,27 +148,6 @@ describe('HandRaiseLeadButton', () => { ...@@ -166,27 +148,6 @@ describe('HandRaiseLeadButton', () => {
}); });
}); });
describe('country & state handling', () => {
beforeEach(() => {
wrapper = createComponent();
});
it.each`
state | display
${'US'} | ${true}
${'CA'} | ${true}
${'NL'} | ${false}
`('displayed $display', async ({ state, display }) => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ countries, states, country: state });
await nextTick();
expect(wrapper.findByTestId('state').exists()).toBe(display);
});
});
describe('form', () => { describe('form', () => {
beforeEach(async () => { beforeEach(async () => {
wrapper = createComponent(); wrapper = createComponent();
...@@ -194,7 +155,7 @@ describe('HandRaiseLeadButton', () => { ...@@ -194,7 +155,7 @@ describe('HandRaiseLeadButton', () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
wrapper.setData({ countries, states, country: 'US', ...formData, comment: 'comment' }); wrapper.setData({ ...FORM_DATA, stateRequired: true, comment: 'comment' });
}); });
describe('successful submission', () => { describe('successful submission', () => {
...@@ -209,7 +170,7 @@ describe('HandRaiseLeadButton', () => { ...@@ -209,7 +170,7 @@ describe('HandRaiseLeadButton', () => {
namespaceId: 1, namespaceId: 1,
comment: 'comment', comment: 'comment',
glmContent: 'some-content', glmContent: 'some-content',
...formData, ...FORM_DATA,
}); });
}); });
...@@ -218,11 +179,10 @@ describe('HandRaiseLeadButton', () => { ...@@ -218,11 +179,10 @@ describe('HandRaiseLeadButton', () => {
expect(wrapper.findByTestId(f).attributes('value')).toBe(''), expect(wrapper.findByTestId(f).attributes('value')).toBe(''),
); );
['company-size', 'country'].forEach((f) => expect(wrapper.findByTestId('company-size').attributes('value')).toBe(undefined);
expect(wrapper.findByTestId(f).attributes('value')).toBe(undefined), expect(wrapper.vm.country).toBe('');
); expect(wrapper.vm.state).toBe('');
expect(wrapper.vm.stateRequired).toBe(false);
expect(wrapper.findByTestId('state').exists()).toBe(false);
}); });
it('tracks successful submission', async () => { it('tracks successful submission', async () => {
......
export const countries = [ export const COUNTRY_WITH_STATES = 'US';
{ id: 'US', name: 'United States' }, export const STATE = 'CA';
export const COUNTRIES = [
{ id: COUNTRY_WITH_STATES, name: 'United States' },
{ id: 'CA', name: 'Canada' }, { id: 'CA', name: 'Canada' },
{ id: 'NL', name: 'Netherlands' }, { id: 'NL', name: 'Netherlands' },
]; ];
export const states = [ export const STATES = [
{ countryId: 'US', id: 'CA', name: 'California' }, { countryId: COUNTRY_WITH_STATES, id: STATE, name: 'California' },
{ countryId: 'CA', id: 'BC', name: 'British Columbia' }, { countryId: 'CA', id: 'BC', name: 'British Columbia' },
]; ];
export const formData = { export const FORM_DATA = {
firstName: 'Joe', firstName: 'Joe',
lastName: 'Doe', lastName: 'Doe',
companyName: 'ACME', companyName: 'ACME',
companySize: '1-99', companySize: '1-99',
phoneNumber: '192919', phoneNumber: '192919',
country: 'US', country: COUNTRY_WITH_STATES,
state: 'CA', state: STATE,
}; };
...@@ -3,30 +3,36 @@ import VueApollo from 'vue-apollo'; ...@@ -3,30 +3,36 @@ import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import CountryOrRegionSelector from 'ee/trials/components/country_or_region_selector.vue'; import CountryOrRegionSelector from 'ee/trials/components/country_or_region_selector.vue';
import { countries, states } from '../../hand_raise_leads/components/mock_data'; import {
import { formData } from './mock_data'; COUNTRIES,
STATES,
COUNTRY_WITH_STATES,
STATE,
} from '../../hand_raise_leads/components/mock_data';
Vue.use(VueApollo); Vue.use(VueApollo);
describe('CountryOrRegionSelector', () => { describe('CountryOrRegionSelector', () => {
let wrapper; let wrapper;
const createComponent = ({ mountFunction = shallowMountExtended } = {}) => { const createComponent = (props = {}) => {
const mockResolvers = { const mockResolvers = {
Query: { Query: {
countries() { countries() {
return [{ id: 'US', name: 'United States' }]; return COUNTRIES;
}, },
states() { states() {
return [{ countryId: 'US', id: 'CA', name: 'California' }]; return STATES;
}, },
}, },
}; };
return mountFunction(CountryOrRegionSelector, { return shallowMountExtended(CountryOrRegionSelector, {
apolloProvider: createMockApollo([], mockResolvers), apolloProvider: createMockApollo([], mockResolvers),
provide: { propsData: {
user: formData, country: COUNTRY_WITH_STATES,
state: STATE,
...props,
}, },
}); });
}; };
...@@ -49,12 +55,6 @@ describe('CountryOrRegionSelector', () => { ...@@ -49,12 +55,6 @@ describe('CountryOrRegionSelector', () => {
`('has the default injected value for $testid', ({ testid, value }) => { `('has the default injected value for $testid', ({ testid, value }) => {
expect(findFormInput(testid).attributes('value')).toBe(value); expect(findFormInput(testid).attributes('value')).toBe(value);
}); });
it('has the correct form input in the form content', () => {
const visibleFields = ['country', 'state'];
visibleFields.forEach((f) => expect(wrapper.findByTestId(f).exists()).toBe(true));
});
}); });
describe.each` describe.each`
...@@ -65,18 +65,66 @@ describe('CountryOrRegionSelector', () => { ...@@ -65,18 +65,66 @@ describe('CountryOrRegionSelector', () => {
`('Country & State handling', ({ country, display }) => { `('Country & State handling', ({ country, display }) => {
describe(`when provided country is set to ${country}`, () => { describe(`when provided country is set to ${country}`, () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent({ country });
}); });
it(`should${display ? '' : ' not'} render the state`, async () => { it(`should${display ? '' : ' not'} render the state`, async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({ countries, states, country });
await nextTick(); await nextTick();
expect(findFormInput('state').exists()).toBe(display); expect(findFormInput('state').exists()).toBe(display);
}); });
}); });
}); });
describe('selection change', () => {
it('emits the change event properly when country is changed', async () => {
wrapper = createComponent();
await findFormInput('country').vm.$emit('change', true);
expect(wrapper.emitted('change')[0]).toStrictEqual([
{ country: 'US', state: 'CA', stateRequired: true },
]);
});
it('emits the change event properly when country is changed with no state required', async () => {
wrapper = createComponent({ country: 'NL' });
await findFormInput('country').vm.$emit('change', true);
expect(wrapper.emitted('change')[0]).toStrictEqual([
{ country: 'NL', state: '', stateRequired: false },
]);
});
it('emits the change event properly when country is changed with state required', async () => {
wrapper = createComponent({ country: 'US', state: '' });
await findFormInput('country').vm.$emit('change', true);
expect(wrapper.emitted('change')[0]).toStrictEqual([
{ country: 'US', state: '', stateRequired: true },
]);
});
it('emits the change event properly when state is not required but has value', async () => {
wrapper = createComponent({ country: 'NL', state: 'CA' });
await findFormInput('country').vm.$emit('change', true);
expect(wrapper.emitted('change')[0]).toStrictEqual([
{ country: 'NL', state: '', stateRequired: false },
]);
});
it('emits the change event properly when state is changed', async () => {
wrapper = createComponent();
await findFormInput('state').vm.$emit('change', true);
expect(wrapper.emitted('change')[0]).toStrictEqual([
{ country: 'US', state: 'CA', stateRequired: true },
]);
});
});
}); });
export const submitPath = '_submit_path_'; export const SUBMIT_PATH = '_submit_path_';
export const formData = { export const FORM_DATA = {
firstName: 'Joe', firstName: 'Joe',
lastName: 'Doe', lastName: 'Doe',
companyName: 'ACME', companyName: 'ACME',
......
...@@ -5,7 +5,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help ...@@ -5,7 +5,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help
import TrialCreateLeadForm from 'ee/trials/components/trial_create_lead_form.vue'; import TrialCreateLeadForm from 'ee/trials/components/trial_create_lead_form.vue';
import { TRIAL_FORM_SUBMIT_TEXT } from 'ee/trials/constants'; import { TRIAL_FORM_SUBMIT_TEXT } from 'ee/trials/constants';
import { trackSaasTrialSubmit } from '~/google_tag_manager'; import { trackSaasTrialSubmit } from '~/google_tag_manager';
import { formData, submitPath } from './mock_data'; import { FORM_DATA, SUBMIT_PATH } from './mock_data';
jest.mock('~/google_tag_manager', () => ({ jest.mock('~/google_tag_manager', () => ({
trackSaasTrialSubmit: jest.fn(), trackSaasTrialSubmit: jest.fn(),
...@@ -21,8 +21,8 @@ describe('TrialCreateLeadForm', () => { ...@@ -21,8 +21,8 @@ describe('TrialCreateLeadForm', () => {
return mountFunction(TrialCreateLeadForm, { return mountFunction(TrialCreateLeadForm, {
localVue, localVue,
provide: { provide: {
submitPath, submitPath: SUBMIT_PATH,
user: formData, user: FORM_DATA,
}, },
}); });
}; };
......
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