Commit 4433f9f4 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch '346620-move-addon-data-to-graphql' into 'master'

Move addon related data to GraphQL

See merge request gitlab-org/gitlab!78426
parents 65161efa 3e6dc6db
......@@ -67,10 +67,8 @@ export default {
return this.isQuantityValid ? total : '';
},
plan() {
return {
...this.plans[0],
isAddon: true,
};
const [plan] = this.plans;
return plan;
},
totalUnits() {
return this.quantity * this.config.quantityPerPack;
......
......@@ -6,6 +6,11 @@ export const planTags = {
STORAGE_PLAN: 'STORAGE_PLAN',
};
/* eslint-enable @gitlab/require-i18n-strings */
export const planCode = {
CI_1000_MINUTES_PLAN: 'ci_minutes',
STORAGE_PLAN: 'storage',
};
export const CUSTOMERSDOT_CLIENT = 'customersDotClient';
export const GITLAB_CLIENT = 'gitlabClient';
export const CUSTOMER_TYPE = 'Customer';
......
......@@ -4,20 +4,27 @@ import VueApollo from 'vue-apollo';
import purchaseFlowResolvers from 'ee/vue_shared/purchase_flow/graphql/resolvers';
import typeDefs from 'ee/vue_shared/purchase_flow/graphql/typedefs.graphql';
import createClient from '~/lib/graphql';
import { GITLAB_CLIENT, CUSTOMERSDOT_CLIENT } from './constants';
import { resolvers } from './graphql/resolvers';
import typeDefsCDot from 'ee/subscriptions/buy_addons_shared/graphql/typedefs.graphql';
import { CUSTOMERSDOT_CLIENT, GITLAB_CLIENT } from 'ee/subscriptions/buy_addons_shared/constants';
import {
customersDotResolvers,
gitLabResolvers,
} from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
Vue.use(VueApollo);
const gitlabClient = createClient(merge({}, resolvers, purchaseFlowResolvers), {
const gitlabClient = createClient(merge({}, gitLabResolvers, purchaseFlowResolvers), {
typeDefs,
});
const customersDotClient = createClient(
{},
{
...customersDotResolvers,
},
{
path: '/-/customers_dot/proxy/graphql',
useGet: true,
typeDefs: typeDefsCDot,
},
);
......
......@@ -3,13 +3,40 @@ import { merge } from 'lodash';
import Api from 'ee/api';
import * as SubscriptionsApi from 'ee/api/subscriptions_api';
import { ERROR_FETCHING_COUNTRIES, ERROR_FETCHING_STATES } from 'ee/subscriptions/constants';
import { COUNTRY_TYPE, STATE_TYPE } from 'ee/subscriptions/buy_addons_shared/constants';
import {
COUNTRY_TYPE,
STATE_TYPE,
CI_MINUTES_PER_PACK,
I18N_CI_MINUTES_PRODUCT_LABEL,
I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT,
planCode,
STORAGE_PER_PACK,
} from 'ee/subscriptions/buy_addons_shared/constants';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import createFlash from '~/flash';
const planData = {
[planCode.CI_1000_MINUTES_PLAN]: {
hasExpiration: false,
isAddon: true,
label: I18N_CI_MINUTES_PRODUCT_LABEL,
productUnit: I18N_CI_MINUTES_PRODUCT_UNIT,
quantityPerPack: CI_MINUTES_PER_PACK,
},
[planCode.STORAGE_PLAN]: {
hasExpiration: true,
isAddon: true,
label: I18N_STORAGE_PRODUCT_LABEL,
productUnit: I18N_STORAGE_PRODUCT_UNIT,
quantityPerPack: STORAGE_PER_PACK,
},
};
// NOTE: These resolvers are temporary and will be removed in the future.
// See https://gitlab.com/gitlab-org/gitlab/-/issues/321643
export const resolvers = {
export const gitLabResolvers = {
Query: {
countries: () => {
return Api.fetchCountries()
......@@ -43,3 +70,13 @@ export const resolvers = {
},
},
};
export const customersDotResolvers = {
Plan: {
hasExpiration: ({ code }) => planData[code]?.hasExpiration,
isAddon: ({ code }) => planData[code]?.isAddon,
label: ({ code }) => planData[code]?.label,
productUnit: ({ code }) => planData[code]?.productUnit,
quantityPerPack: ({ code }) => planData[code]?.quantityPerPack,
},
};
type Plan {
id: Int!
name: String!
code: String!
pricePerYear: Int!
label: String!
isAddon: Boolean!
hasExpiration: Boolean!
productUnit: String!
quantityPerPack: String!
}
enum PlanTag {
CI_1000_MINUTES_PLAN
STORAGE_PLAN
}
......@@ -4,5 +4,10 @@ query getPlans($tags: [PlanTag!]) {
name
code
pricePerYear
hasExpiration @client
isAddon @client
label @client
productUnit @client
quantityPerPack @client
}
}
......@@ -42,7 +42,7 @@ localVue.use(VueApollo);
describe('Buy Addons Shared App', () => {
let wrapper;
function createComponent(apolloProvider, propsData) {
async function createComponent(apolloProvider, propsData) {
wrapper = shallowMountExtended(App, {
localVue,
apolloProvider,
......@@ -54,7 +54,7 @@ describe('Buy Addons Shared App', () => {
SummaryDetails,
},
});
return waitForPromises();
await waitForPromises();
}
const STORAGE_ADDON_PROPS = {
......@@ -112,10 +112,10 @@ describe('Buy Addons Shared App', () => {
describe('Storage', () => {
describe('when data is received', () => {
beforeEach(() => {
beforeEach(async () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockStoragePlans } });
const mockApollo = createMockApolloProvider({ plansQueryMock });
createComponent(mockApollo, STORAGE_ADDON_PROPS);
await createComponent(mockApollo, STORAGE_ADDON_PROPS);
});
it('should display the root element', () => {
......@@ -235,10 +235,10 @@ describe('Buy Addons Shared App', () => {
describe('CI Minutes', () => {
describe('when data is received', () => {
beforeEach(() => {
beforeEach(async () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } });
const mockApollo = createMockApolloProvider({ plansQueryMock });
createComponent(mockApollo, CI_MINUTES_ADDON_PROPS);
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS);
});
it('should display the root element', () => {
......
import Api from 'ee/api';
import * as SubscriptionsApi from 'ee/api/subscriptions_api';
import { resolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { gitLabResolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { ERROR_FETCHING_COUNTRIES, ERROR_FETCHING_STATES } from 'ee/subscriptions/constants';
import createFlash from '~/flash';
......@@ -58,7 +58,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('returns an array of countries with typename', async () => {
const result = await resolvers.Query.countries();
const result = await gitLabResolvers.Query.countries();
expect(createFlash).not.toHaveBeenCalled();
expect(result).toStrictEqual([
......@@ -74,7 +74,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('shows a flash message', async () => {
await resolvers.Query.countries();
await gitLabResolvers.Query.countries();
expect(createFlash).toHaveBeenCalledWith({ message: ERROR_FETCHING_COUNTRIES });
});
......@@ -88,7 +88,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('returns an array of states with typename', async () => {
const result = await resolvers.Query.states(null, { countryId: 1 });
const result = await gitLabResolvers.Query.states(null, { countryId: 1 });
expect(createFlash).not.toHaveBeenCalled();
expect(result).toStrictEqual([{ id: 'CA', name: 'California', __typename: 'State' }]);
......@@ -101,7 +101,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('shows a flash message', async () => {
await resolvers.Query.states(null, { countryId: 1 });
await gitLabResolvers.Query.states(null, { countryId: 1 });
expect(createFlash).toHaveBeenCalledWith({ message: ERROR_FETCHING_STATES });
});
......@@ -113,7 +113,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
it('calls the REST api', async () => {
const expectedArgs = { groupId: 1, customer, subscription };
await resolvers.Mutation.purchaseMinutes(null, expectedArgs);
await gitLabResolvers.Mutation.purchaseMinutes(null, expectedArgs);
expect(SubscriptionsApi.createSubscription).toHaveBeenCalledWith(1, customer, subscription);
});
......@@ -124,7 +124,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('returns an error array', async () => {
const result = await resolvers.Mutation.purchaseMinutes(null, {
const result = await gitLabResolvers.Mutation.purchaseMinutes(null, {
groupId: 1,
customer,
subscription,
......@@ -140,7 +140,7 @@ describe('~/subscriptions/buy_addons_shared/graphql/resolvers', () => {
});
it('returns a redirect location', async () => {
const result = await resolvers.Mutation.purchaseMinutes(null, {
const result = await gitLabResolvers.Mutation.purchaseMinutes(null, {
groupId: 1,
customer,
subscription,
......
import { mount, createLocalVue } from '@vue/test-utils';
import { merge } from 'lodash';
import VueApollo from 'vue-apollo';
import { resolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { gitLabResolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { STEPS } from 'ee/subscriptions/constants';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import BillingAddress from 'ee/vue_shared/purchase_flow/components/checkout/billing_address.vue';
......@@ -28,7 +28,7 @@ describe('Billing Address', () => {
const createComponent = (apolloLocalState = {}) => {
const apolloProvider = createMockApolloProvider(STEPS, STEPS[1], {
...resolvers,
...gitLabResolvers,
...apolloResolvers,
});
apolloProvider.clients.defaultClient.cache.writeQuery({
......
......@@ -5,6 +5,7 @@ import orderPreviewQuery from 'ee/subscriptions/graphql/queries/order_preview.cu
import { createMockClient } from 'helpers/mock_apollo_helper';
import { CUSTOMERSDOT_CLIENT } from 'ee/subscriptions/buy_addons_shared/constants';
import { mockDefaultCache, mockOrderPreview } from 'ee_jest/subscriptions/mock_data';
import { customersDotResolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
export function createMockApolloProvider(mockResponses = {}, dataset = {}) {
const {
......@@ -17,10 +18,13 @@ export function createMockApolloProvider(mockResponses = {}, dataset = {}) {
const { quantity } = dataset;
const mockDefaultClient = createMockClient();
const mockCustomersDotClient = createMockClient([
[plansQuery, plansQueryMock],
[orderPreviewQuery, orderPreviewQueryMock],
]);
const mockCustomersDotClient = createMockClient(
[
[plansQuery, plansQueryMock],
[orderPreviewQuery, orderPreviewQueryMock],
],
customersDotResolvers,
);
const apolloProvider = new VueApollo({
defaultClient: mockDefaultClient,
......
......@@ -5,7 +5,7 @@ import {
mockParsedNamespaces,
stateData as initialStateData,
} from 'ee_jest/subscriptions/mock_data';
import { resolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { gitLabResolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { STEPS } from 'ee/subscriptions/constants';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import PaymentMethod from 'ee/vue_shared/purchase_flow/components/checkout/payment_method.vue';
......@@ -26,9 +26,7 @@ describe('Payment Method', () => {
const isStepValid = () => wrapper.findComponent(Step).props('isValid');
const createComponent = (apolloLocalState = {}) => {
const apolloProvider = createMockApolloProvider(STEPS, STEPS[2], {
...resolvers,
});
const apolloProvider = createMockApolloProvider(STEPS, STEPS[2], gitLabResolvers);
apolloProvider.clients.defaultClient.cache.writeQuery({
query: stateQuery,
data: merge({}, initialStateData, apolloLocalState),
......
......@@ -4,7 +4,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import { merge } from 'lodash';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { resolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { gitLabResolvers } from 'ee/subscriptions/buy_addons_shared/graphql/resolvers';
import { STEPS } from 'ee/subscriptions/constants';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import Zuora from 'ee/vue_shared/purchase_flow/components/checkout/zuora.vue';
......@@ -20,9 +20,7 @@ describe('Zuora', () => {
let wrapper;
const createComponent = (props = {}, data = {}, apolloLocalState = {}) => {
const apolloProvider = createMockApolloProvider(STEPS, STEPS[1], {
...resolvers,
});
const apolloProvider = createMockApolloProvider(STEPS, STEPS[1], gitLabResolvers);
apolloProvider.clients.defaultClient.cache.writeQuery({
query: stateQuery,
data: merge({}, initialStateData, apolloLocalState),
......
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