Commit f0f0f6b3 authored by Phil Hughes's avatar Phil Hughes

Merge branch '323357-mlunoe-pass-ci-plans-data-in-frontend' into 'master'

Feat(buy_minutes): pass CI Minutes data to frontend

See merge request gitlab-org/gitlab!57096
parents 9db767b7 63cd043b
import mountSubscriptionsApplication from 'ee/subscriptions/buy_minutes'; import mountSubscriptionsApplication from 'ee/subscriptions/buy_minutes';
mountSubscriptionsApplication(); mountSubscriptionsApplication(document.getElementById('js-buy-minutes'));
import Vue from 'vue'; import Vue from 'vue';
import ensureData from '~/ensure_data';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import App from './components/app.vue'; import App from './components/app.vue';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
import seedQuery from './graphql/queries/seed.query.graphql'; import seedQuery from './graphql/queries/seed.query.graphql';
import { parseData } from './utils';
const arrayToGraphqlArray = (arr, typename) => const arrayToGraphqlArray = (arr, typename) =>
Array.from(arr, (item) => Object.assign(item, { __typename: typename })); Array.from(arr, (item) => Object.assign(item, { __typename: typename }));
...@@ -24,8 +26,15 @@ const writeInitialDataToApolloProvider = (dataset) => { ...@@ -24,8 +26,15 @@ const writeInitialDataToApolloProvider = (dataset) => {
}); });
}; };
export default () => { export default (el) => {
const el = document.getElementById('js-buy-minutes'); if (!el) {
return null;
}
const ExtendedApp = ensureData(App, {
parseData,
data: el.dataset,
});
writeInitialDataToApolloProvider(el.dataset); writeInitialDataToApolloProvider(el.dataset);
...@@ -33,7 +42,7 @@ export default () => { ...@@ -33,7 +42,7 @@ export default () => {
el, el,
apolloProvider, apolloProvider,
render(createElement) { render(createElement) {
return createElement(App); return createElement(ExtendedApp);
}, },
}); });
}; };
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
export function parseData(dataset) {
const { ciMinutesPlans } = dataset;
return {
ciMinutesPlans: convertObjectPropsToCamelCase(JSON.parse(ciMinutesPlans), {
deep: true,
}),
};
}
import { GlEmptyState } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { createWrapper } from '@vue/test-utils';
import initBuyMinutesApp from 'ee/subscriptions/buy_minutes';
import * as utils from 'ee/subscriptions/buy_minutes/utils';
import StepOrderApp from 'ee/vue_shared/components/step_order_app.vue';
import { mockCiMinutesPlans, mockParsedCiMinutesPlans } from './mock_data';
jest.mock('ee/subscriptions/buy_minutes/utils');
describe('initBuyMinutesApp', () => {
let vm;
let wrapper;
function createComponent() {
const el = document.createElement('div');
Object.assign(el.dataset, { ciMinutesPlans: mockCiMinutesPlans, groupData: '[]' });
vm = initBuyMinutesApp(el).$mount();
wrapper = createWrapper(vm);
}
beforeEach(() => {
Sentry.captureException = jest.fn();
});
afterEach(() => {
if (vm) {
vm.$destroy();
}
wrapper.destroy();
vm = null;
Sentry.captureException.mockClear();
utils.parseData.mockClear();
});
describe('when parsing fails', () => {
it('displays the EmptyState', () => {
utils.parseData.mockImplementation(() => {
throw new Error();
});
createComponent();
expect(wrapper.find(StepOrderApp).exists()).toBe(false);
expect(wrapper.find(GlEmptyState).exists()).toBe(true);
expect(Sentry.captureException).not.toHaveBeenCalled();
});
});
describe('when parsing succeeds', () => {
it('displays the StepOrderApp', () => {
utils.parseData.mockImplementation(() => mockParsedCiMinutesPlans);
createComponent();
expect(wrapper.find(GlEmptyState).exists()).toBe(false);
expect(wrapper.find(StepOrderApp).exists()).toBe(true);
expect(Sentry.captureException).not.toHaveBeenCalled();
});
});
});
export const mockCiMinutesPlans =
'[{"deprecated":false,"name":"1000 CI minutes pack","code":"ci_minutes","active":true,"free":null,"price_per_month":0.8333333333333334,"price_per_year":10.0,"features":null,"about_page_href":null,"hide_deprecated_card":false}]';
export const mockParsedCiMinutesPlans = [
{
deprecated: false,
name: '1000 CI minutes pack',
code: 'ci_minutes',
active: true,
free: null,
pricePerMonth: 0.8333333333333334,
pricePerYear: 10.0,
features: null,
aboutPageHref: null,
hideDeprecatedCard: false,
},
];
import { parseData } from 'ee/subscriptions/buy_minutes/utils';
import { mockCiMinutesPlans, mockParsedCiMinutesPlans } from './mock_data';
describe('utils', () => {
describe('#parseData', () => {
describe.each`
ciMinutesPlans | parsedCiMinutesPlans | throws
${'[]'} | ${[]} | ${false}
${'null'} | ${{}} | ${false}
${mockCiMinutesPlans} | ${mockParsedCiMinutesPlans} | ${false}
${''} | ${{}} | ${true}
`('parameter decoding', ({ ciMinutesPlans, parsedCiMinutesPlans, throws }) => {
it(`decodes ${ciMinutesPlans} to ${parsedCiMinutesPlans}`, () => {
if (throws) {
expect(() => {
parseData({ ciMinutesPlans });
}).toThrow();
} else {
const result = parseData({ ciMinutesPlans });
expect(result.ciMinutesPlans).toEqual(parsedCiMinutesPlans);
}
});
});
});
});
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