Commit 717a73a6 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch '346620-automagically-obtain-translations' into 'master'

Resolve "Move add-on related data to GraphQL"

See merge request gitlab-org/gitlab!78436
parents 948a862c 3b9b980c
...@@ -20,16 +20,7 @@ export default { ...@@ -20,16 +20,7 @@ export default {
GlAlert, GlAlert,
OrderSummary, OrderSummary,
}, },
props: { inject: ['tags', 'i18n'],
config: {
required: true,
type: Object,
},
tags: {
required: true,
type: Array,
},
},
data() { data() {
return { return {
hasError: false, hasError: false,
...@@ -50,14 +41,14 @@ export default { ...@@ -50,14 +41,14 @@ export default {
return Number.isFinite(this.quantity) && this.quantity > 0; return Number.isFinite(this.quantity) && this.quantity > 0;
}, },
formulaText() { formulaText() {
const formulaText = this.isQuantityValid ? this.config.formula : this.config.formulaWithAlert; const formulaText = this.isQuantityValid ? this.i18n.formula : this.i18n.formulaWithAlert;
return sprintf(formulaText, { return sprintf(formulaText, {
quantity: formatNumber(this.config.quantityPerPack), quantity: formatNumber(this.plan.quantityPerPack),
units: this.config.productUnit, units: this.plan.productUnit,
}); });
}, },
formulaTotal() { formulaTotal() {
const total = sprintf(this.config.formulaTotal, { const total = sprintf(this.i18n.formulaTotal, {
quantity: formatNumber(this.totalUnits), quantity: formatNumber(this.totalUnits),
}); });
return this.isQuantityValid ? total : ''; return this.isQuantityValid ? total : '';
...@@ -67,20 +58,20 @@ export default { ...@@ -67,20 +58,20 @@ export default {
return plan; return plan;
}, },
totalUnits() { totalUnits() {
return this.quantity * this.config.quantityPerPack; return this.quantity * this.plan.quantityPerPack;
}, },
summaryTitle() { summaryTitle() {
return sprintf(this.config.summaryTitle(this.quantity), { quantity: this.quantity }); return sprintf(this.i18n.summaryTitle(this.quantity), { quantity: this.quantity });
}, },
summaryTotal() { summaryTotal() {
return sprintf(this.config.summaryTotal, { return sprintf(this.i18n.summaryTotal, {
quantity: formatNumber(this.totalUnits), quantity: formatNumber(this.totalUnits),
}); });
}, },
}, },
methods: { methods: {
pricePerUnitLabel(price) { pricePerUnitLabel(price) {
return sprintf(this.config.pricePerUnit, { return sprintf(this.i18n.pricePerUnit, {
selectedPlanPrice: price, selectedPlanPrice: price,
}); });
}, },
...@@ -137,10 +128,10 @@ export default { ...@@ -137,10 +128,10 @@ export default {
<checkout :plan="plan"> <checkout :plan="plan">
<template #purchase-details> <template #purchase-details>
<addon-purchase-details <addon-purchase-details
:product-label="config.productLabel" :product-label="plan.label"
:quantity="quantity" :quantity="quantity"
:show-alert="true" :show-alert="true"
:alert-text="config.alertText" :alert-text="i18n.alertText"
> >
<template #formula> <template #formula>
{{ formulaText }} {{ formulaText }}
...@@ -162,8 +153,8 @@ export default { ...@@ -162,8 +153,8 @@ export default {
> >
<order-summary <order-summary
:plan="plan" :plan="plan"
:title="config.title" :title="i18n.title"
:purchase-has-expiration="config.hasExpiration" :purchase-has-expiration="plan.hasExpiration"
@alertError="alertError" @alertError="alertError"
> >
<template #price-per-unit="{ price }"> <template #price-per-unit="{ price }">
......
...@@ -6,10 +6,6 @@ export const planTags = { ...@@ -6,10 +6,6 @@ export const planTags = {
STORAGE_PLAN: 'STORAGE_PLAN', STORAGE_PLAN: 'STORAGE_PLAN',
}; };
/* eslint-enable @gitlab/require-i18n-strings */ /* 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 CUSTOMERSDOT_CLIENT = 'customersDotClient';
export const GITLAB_CLIENT = 'gitlabClient'; export const GITLAB_CLIENT = 'gitlabClient';
...@@ -26,40 +22,25 @@ export const STATE_TYPE = 'State'; ...@@ -26,40 +22,25 @@ export const STATE_TYPE = 'State';
export const CI_MINUTES_PER_PACK = 1000; export const CI_MINUTES_PER_PACK = 1000;
export const STORAGE_PER_PACK = 10; export const STORAGE_PER_PACK = 10;
// CI Minutes addon data translations
export const I18N_CI_MINUTES_PRODUCT_LABEL = s__('Checkout|CI minute pack'); export const I18N_CI_MINUTES_PRODUCT_LABEL = s__('Checkout|CI minute pack');
export const I18N_CI_MINUTES_PRODUCT_UNIT = s__('Checkout|minutes'); export const I18N_CI_MINUTES_PRODUCT_UNIT = s__('Checkout|minutes');
export const I18N_CI_MINUTES_FORMULA_TOTAL = s__('Checkout|%{quantity} CI minutes');
export const i18nCIMinutesSummaryTitle = (quantity) =>
n__('Checkout|%d CI minute pack', 'Checkout|%d CI minute packs', quantity);
export const I18N_CI_MINUTES_SUMMARY_TOTAL = s__('Checkout|Total minutes: %{quantity}');
export const I18N_CI_MINUTES_ALERT_TEXT = s__(
"Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year.",
);
export const I18N_CI_MINUTES_PRICE_PER_UNIT = s__(
'Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes',
);
export const I18N_CI_MINUTES_TITLE = s__("Checkout|%{name}'s CI minutes");
// Storage addon translations
export const I18N_STORAGE_PRODUCT_LABEL = s__('Checkout|Storage packs'); export const I18N_STORAGE_PRODUCT_LABEL = s__('Checkout|Storage packs');
export const I18N_STORAGE_PRODUCT_UNIT = s__('Checkout|GB'); export const I18N_STORAGE_PRODUCT_UNIT = s__('Checkout|GB');
export const I18N_STORAGE_FORMULA_TOTAL = s__('Checkout|%{quantity} GB of storage');
export const i18nStorageSummaryTitle = (quantity) =>
n__('Checkout|%{quantity} storage pack', 'Checkout|%{quantity} storage packs', quantity);
export const I18N_STORAGE_SUMMARY_TOTAL = s__('Checkout|Total storage: %{quantity} GB');
export const I18N_STORAGE_PRICE_PER_UNIT = s__(
'Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year',
);
export const I18N_STORAGE_TITLE = s__("Checkout|%{name}'s storage subscription");
export const I18N_STORAGE_TOOLTIP_NOTE = s__( export const I18N_STORAGE_TOOLTIP_NOTE = s__(
'Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly.', 'Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly.',
); );
// Shared addon translations
export const I18N_DETAILS_STEP_TITLE = s__('Checkout|Purchase details'); export const I18N_DETAILS_STEP_TITLE = s__('Checkout|Purchase details');
export const I18N_DETAILS_NEXT_STEP_BUTTON_TEXT = s__('Checkout|Continue to billing'); export const I18N_DETAILS_NEXT_STEP_BUTTON_TEXT = s__('Checkout|Continue to billing');
export const I18N_DETAILS_INVALID_QUANTITY_MESSAGE = s__('Checkout|Enter a number greater than 0'); export const I18N_DETAILS_INVALID_QUANTITY_MESSAGE = s__('Checkout|Enter a number greater than 0');
export const I18N_DETAILS_FORMULA = s__('Checkout|x %{quantity} %{units} per pack ='); export const I18N_DETAILS_FORMULA = s__('Checkout|x %{quantity} %{units} per pack =');
export const I18N_DETAILS_FORMULA_WITH_ALERT = s__('Checkout|x %{quantity} %{units} per pack'); export const I18N_DETAILS_FORMULA_WITH_ALERT = s__('Checkout|x %{quantity} %{units} per pack');
// Summary translations
export const I18N_SUMMARY_QUANTITY = s__('Checkout|(x%{quantity})'); export const I18N_SUMMARY_QUANTITY = s__('Checkout|(x%{quantity})');
export const I18N_SUMMARY_DATES = s__('Checkout|%{startDate} - %{endDate}'); export const I18N_SUMMARY_DATES = s__('Checkout|%{startDate} - %{endDate}');
export const I18N_SUMMARY_SUBTOTAL = s__('Checkout|Subtotal'); export const I18N_SUMMARY_SUBTOTAL = s__('Checkout|Subtotal');
...@@ -72,3 +53,30 @@ export const I18N_SUMMARY_TOTAL = s__('Checkout|Total'); ...@@ -72,3 +53,30 @@ export const I18N_SUMMARY_TOTAL = s__('Checkout|Total');
export const I18N_API_ERROR = s__( export const I18N_API_ERROR = s__(
'Checkout|An unknown error has occurred. Please try again by refreshing this page.', 'Checkout|An unknown error has occurred. Please try again by refreshing this page.',
); );
// Addon label translations
export const I18N_CI_1000_MINUTES_PLAN = {
alertText: s__(
"Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year.",
),
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: s__('Checkout|%{quantity} CI minutes'),
pricePerUnit: s__('Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes'),
summaryTitle: (quantity) =>
n__('Checkout|%d CI minute pack', 'Checkout|%d CI minute packs', quantity),
summaryTotal: s__('Checkout|Total minutes: %{quantity}'),
title: s__("Checkout|%{name}'s CI minutes"),
};
export const I18N_STORAGE_PLAN = {
alertText: '',
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: s__('Checkout|%{quantity} GB of storage'),
pricePerUnit: s__('Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year'),
summaryTitle: (quantity) =>
n__('Checkout|%{quantity} storage pack', 'Checkout|%{quantity} storage packs', quantity),
summaryTotal: s__('Checkout|Total storage: %{quantity} GB'),
title: s__("Checkout|%{name}'s storage subscription"),
};
...@@ -11,12 +11,16 @@ import { ...@@ -11,12 +11,16 @@ import {
I18N_CI_MINUTES_PRODUCT_UNIT, I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_STORAGE_PRODUCT_LABEL, I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT, I18N_STORAGE_PRODUCT_UNIT,
planCode,
STORAGE_PER_PACK, STORAGE_PER_PACK,
} from 'ee/subscriptions/buy_addons_shared/constants'; } from 'ee/subscriptions/buy_addons_shared/constants';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql'; import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import createFlash from '~/flash'; import createFlash from '~/flash';
const planCode = {
CI_1000_MINUTES_PLAN: 'ci_minutes',
STORAGE_PLAN: 'storage',
};
const planData = { const planData = {
[planCode.CI_1000_MINUTES_PLAN]: { [planCode.CI_1000_MINUTES_PLAN]: {
hasExpiration: false, hasExpiration: false,
......
<script>
import BuyAddonsApp from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import {
CI_MINUTES_PER_PACK,
planTags,
I18N_CI_MINUTES_PRICE_PER_UNIT,
I18N_CI_MINUTES_PRODUCT_LABEL,
I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_DETAILS_FORMULA_WITH_ALERT,
I18N_CI_MINUTES_FORMULA_TOTAL,
i18nCIMinutesSummaryTitle,
I18N_CI_MINUTES_SUMMARY_TOTAL,
I18N_CI_MINUTES_ALERT_TEXT,
I18N_CI_MINUTES_TITLE,
} from 'ee/subscriptions/buy_addons_shared/constants';
export default {
components: {
BuyAddonsApp,
},
computed: {
tags() {
return [planTags.CI_1000_MINUTES_PLAN];
},
config() {
// These will move into the GraphQL store. See: https://gitlab.com/gitlab-org/gitlab/-/issues/346620
return {
alertText: I18N_CI_MINUTES_ALERT_TEXT,
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_CI_MINUTES_FORMULA_TOTAL,
hasExpiration: false,
pricePerUnit: I18N_CI_MINUTES_PRICE_PER_UNIT,
productLabel: I18N_CI_MINUTES_PRODUCT_LABEL,
productUnit: I18N_CI_MINUTES_PRODUCT_UNIT,
quantityPerPack: CI_MINUTES_PER_PACK,
summaryTitle: i18nCIMinutesSummaryTitle,
summaryTotal: I18N_CI_MINUTES_SUMMARY_TOTAL,
title: I18N_CI_MINUTES_TITLE,
};
},
},
};
</script>
<template>
<buy-addons-app :config="config" :tags="tags" />
</template>
import Vue from 'vue'; import Vue from 'vue';
import ensureData from '~/ensure_data'; import ensureData from '~/ensure_data';
import apolloProvider from '../buy_addons_shared/graphql'; import { planTags, I18N_CI_1000_MINUTES_PLAN } from 'ee/subscriptions/buy_addons_shared/constants';
import App from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import { writeInitialDataToApolloCache } from '../buy_addons_shared/utils'; import { writeInitialDataToApolloCache } from '../buy_addons_shared/utils';
import App from './components/app.vue'; import apolloProvider from '../buy_addons_shared/graphql';
export default (el) => { export default (el) => {
if (!el) { if (!el) {
...@@ -13,6 +14,10 @@ export default (el) => { ...@@ -13,6 +14,10 @@ export default (el) => {
parseData: writeInitialDataToApolloCache.bind(null, apolloProvider), parseData: writeInitialDataToApolloCache.bind(null, apolloProvider),
data: el.dataset, data: el.dataset,
shouldLog: true, shouldLog: true,
provide: {
tags: [planTags.CI_1000_MINUTES_PLAN],
i18n: I18N_CI_1000_MINUTES_PLAN,
},
}); });
return new Vue({ return new Vue({
......
<script>
import BuyAddonsApp from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import {
I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_STORAGE_FORMULA_TOTAL,
I18N_DETAILS_FORMULA_WITH_ALERT,
i18nStorageSummaryTitle,
I18N_STORAGE_SUMMARY_TOTAL,
I18N_STORAGE_TITLE,
I18N_STORAGE_PRICE_PER_UNIT,
planTags,
STORAGE_PER_PACK,
} from 'ee/subscriptions/buy_addons_shared/constants';
export default {
name: 'BuyStorageApp',
components: {
BuyAddonsApp,
},
computed: {
tags() {
return [planTags.STORAGE_PLAN];
},
config() {
// These will move into the GraphQL store. See: https://gitlab.com/gitlab-org/gitlab/-/issues/346620
return {
alertText: '',
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_STORAGE_FORMULA_TOTAL,
hasExpiration: true,
pricePerUnit: I18N_STORAGE_PRICE_PER_UNIT,
productLabel: I18N_STORAGE_PRODUCT_LABEL,
productUnit: I18N_STORAGE_PRODUCT_UNIT,
quantityPerPack: STORAGE_PER_PACK,
summaryTitle: i18nStorageSummaryTitle,
summaryTotal: I18N_STORAGE_SUMMARY_TOTAL,
title: I18N_STORAGE_TITLE,
};
},
},
};
</script>
<template>
<buy-addons-app :config="config" :tags="tags" />
</template>
import Vue from 'vue'; import Vue from 'vue';
import ensureData from '~/ensure_data'; import ensureData from '~/ensure_data';
import { planTags, I18N_STORAGE_PLAN } from 'ee/subscriptions/buy_addons_shared/constants';
import App from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import apolloProvider from '../buy_addons_shared/graphql'; import apolloProvider from '../buy_addons_shared/graphql';
import { writeInitialDataToApolloCache } from '../buy_addons_shared/utils'; import { writeInitialDataToApolloCache } from '../buy_addons_shared/utils';
import App from './components/app.vue';
export default (el) => { export default (el) => {
if (!el) { if (!el) {
...@@ -13,10 +14,15 @@ export default (el) => { ...@@ -13,10 +14,15 @@ export default (el) => {
parseData: writeInitialDataToApolloCache.bind(null, apolloProvider), parseData: writeInitialDataToApolloCache.bind(null, apolloProvider),
data: el.dataset, data: el.dataset,
shouldLog: true, shouldLog: true,
provide: {
tags: [planTags.STORAGE_PLAN],
i18n: I18N_STORAGE_PLAN,
},
}); });
return new Vue({ return new Vue({
el, el,
name: 'BuyStorage',
apolloProvider, apolloProvider,
render(createElement) { render(createElement) {
return createElement(extendedApp); return createElement(extendedApp);
......
...@@ -3,27 +3,10 @@ import { createLocalVue } from '@vue/test-utils'; ...@@ -3,27 +3,10 @@ import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { pick } from 'lodash'; import { pick } from 'lodash';
import { import {
CI_MINUTES_PER_PACK, I18N_CI_1000_MINUTES_PLAN,
I18N_CI_MINUTES_PRICE_PER_UNIT, I18N_STORAGE_PLAN,
I18N_CI_MINUTES_PRODUCT_LABEL,
I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_CI_MINUTES_FORMULA_TOTAL,
i18nCIMinutesSummaryTitle,
I18N_CI_MINUTES_SUMMARY_TOTAL,
I18N_CI_MINUTES_ALERT_TEXT,
I18N_CI_MINUTES_TITLE,
I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_STORAGE_FORMULA_TOTAL,
I18N_DETAILS_FORMULA_WITH_ALERT,
i18nStorageSummaryTitle,
I18N_STORAGE_SUMMARY_TOTAL,
I18N_STORAGE_TITLE,
I18N_STORAGE_PRICE_PER_UNIT,
I18N_API_ERROR, I18N_API_ERROR,
planTags, planTags,
STORAGE_PER_PACK,
} from 'ee/subscriptions/buy_addons_shared/constants'; } from 'ee/subscriptions/buy_addons_shared/constants';
import Checkout from 'ee/subscriptions/buy_addons_shared/components/checkout.vue'; import Checkout from 'ee/subscriptions/buy_addons_shared/components/checkout.vue';
import AddonPurchaseDetails from 'ee/subscriptions/buy_addons_shared/components/checkout/addon_purchase_details.vue'; import AddonPurchaseDetails from 'ee/subscriptions/buy_addons_shared/components/checkout/addon_purchase_details.vue';
...@@ -41,11 +24,11 @@ localVue.use(VueApollo); ...@@ -41,11 +24,11 @@ localVue.use(VueApollo);
describe('Buy Addons Shared App', () => { describe('Buy Addons Shared App', () => {
let wrapper; let wrapper;
async function createComponent(apolloProvider, propsData) { async function createComponent(apolloProvider, injectedProps) {
wrapper = shallowMountExtended(App, { wrapper = shallowMountExtended(App, {
localVue, localVue,
apolloProvider, apolloProvider,
propsData, provide: injectedProps,
stubs: { stubs: {
Checkout, Checkout,
AddonPurchaseDetails, AddonPurchaseDetails,
...@@ -56,40 +39,6 @@ describe('Buy Addons Shared App', () => { ...@@ -56,40 +39,6 @@ describe('Buy Addons Shared App', () => {
await waitForPromises(); await waitForPromises();
} }
const STORAGE_ADDON_PROPS = {
config: {
alertText: '',
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_STORAGE_FORMULA_TOTAL,
hasExpiration: true,
pricePerUnit: I18N_STORAGE_PRICE_PER_UNIT,
productLabel: I18N_STORAGE_PRODUCT_LABEL,
productUnit: I18N_STORAGE_PRODUCT_UNIT,
quantityPerPack: STORAGE_PER_PACK,
summaryTitle: i18nStorageSummaryTitle,
summaryTotal: I18N_STORAGE_SUMMARY_TOTAL,
title: I18N_STORAGE_TITLE,
},
tags: [planTags.STORAGE_PLAN],
};
const CI_MINUTES_ADDON_PROPS = {
config: {
alertText: I18N_CI_MINUTES_ALERT_TEXT,
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_CI_MINUTES_FORMULA_TOTAL,
hasExpiration: false,
pricePerUnit: I18N_CI_MINUTES_PRICE_PER_UNIT,
productLabel: I18N_CI_MINUTES_PRODUCT_LABEL,
productUnit: I18N_CI_MINUTES_PRODUCT_UNIT,
quantityPerPack: CI_MINUTES_PER_PACK,
summaryTitle: i18nCIMinutesSummaryTitle,
summaryTotal: I18N_CI_MINUTES_SUMMARY_TOTAL,
title: I18N_CI_MINUTES_TITLE,
},
tags: [planTags.CI_1000_MINUTES_PLAN],
};
const getStoragePlan = () => pick(mockStoragePlans[0], ['id', 'code', 'pricePerYear', 'name']); const getStoragePlan = () => pick(mockStoragePlans[0], ['id', 'code', 'pricePerYear', 'name']);
const getCiMinutesPlan = () => const getCiMinutesPlan = () =>
pick(mockCiMinutesPlans[0], ['id', 'code', 'pricePerYear', 'name']); pick(mockCiMinutesPlans[0], ['id', 'code', 'pricePerYear', 'name']);
...@@ -108,11 +57,15 @@ describe('Buy Addons Shared App', () => { ...@@ -108,11 +57,15 @@ describe('Buy Addons Shared App', () => {
}); });
describe('Storage', () => { describe('Storage', () => {
const injectedProps = {
tags: [planTags.STORAGE_PLAN],
i18n: I18N_STORAGE_PLAN,
};
describe('when data is received', () => { describe('when data is received', () => {
beforeEach(async () => { beforeEach(async () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockStoragePlans } }); const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockStoragePlans } });
const mockApollo = createMockApolloProvider({ plansQueryMock }); const mockApollo = createMockApolloProvider({ plansQueryMock });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
}); });
it('should display the root element', () => { it('should display the root element', () => {
...@@ -129,7 +82,7 @@ describe('Buy Addons Shared App', () => { ...@@ -129,7 +82,7 @@ describe('Buy Addons Shared App', () => {
it('provides the correct props to order summary', () => { it('provides the correct props to order summary', () => {
expect(findOrderSummary().props()).toMatchObject({ expect(findOrderSummary().props()).toMatchObject({
plan: { ...getStoragePlan, isAddon: true }, plan: { ...getStoragePlan, isAddon: true },
title: I18N_STORAGE_TITLE, title: I18N_STORAGE_PLAN.title,
}); });
}); });
...@@ -153,7 +106,7 @@ describe('Buy Addons Shared App', () => { ...@@ -153,7 +106,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: null }), plansQueryMock: jest.fn().mockResolvedValue({ data: null }),
}); });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -163,7 +116,7 @@ describe('Buy Addons Shared App', () => { ...@@ -163,7 +116,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: null } }), plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: null } }),
}); });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -173,7 +126,7 @@ describe('Buy Addons Shared App', () => { ...@@ -173,7 +126,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: {} } }), plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: {} } }),
}); });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -185,7 +138,7 @@ describe('Buy Addons Shared App', () => { ...@@ -185,7 +138,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockRejectedValue(new Error('An error happened!')), plansQueryMock: jest.fn().mockRejectedValue(new Error('An error happened!')),
}); });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -196,7 +149,7 @@ describe('Buy Addons Shared App', () => { ...@@ -196,7 +149,7 @@ describe('Buy Addons Shared App', () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockStoragePlans } }); const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockStoragePlans } });
it('shows labels correctly for 1 pack', async () => { it('shows labels correctly for 1 pack', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }); const mockApollo = createMockApolloProvider({ plansQueryMock });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText( expect(findQuantityText().text()).toMatchInterpolatedText(
'x 10 GB per pack = 10 GB of storage', 'x 10 GB per pack = 10 GB of storage',
...@@ -209,7 +162,7 @@ describe('Buy Addons Shared App', () => { ...@@ -209,7 +162,7 @@ describe('Buy Addons Shared App', () => {
it('shows labels correctly for 2 packs', async () => { it('shows labels correctly for 2 packs', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: 2 }); const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: 2 });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText( expect(findQuantityText().text()).toMatchInterpolatedText(
'x 10 GB per pack = 20 GB of storage', 'x 10 GB per pack = 20 GB of storage',
...@@ -222,7 +175,7 @@ describe('Buy Addons Shared App', () => { ...@@ -222,7 +175,7 @@ describe('Buy Addons Shared App', () => {
it('does not show labels if input is invalid', async () => { it('does not show labels if input is invalid', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: -1 }); const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: -1 });
await createComponent(mockApollo, STORAGE_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText('x 10 GB per pack'); expect(findQuantityText().text()).toMatchInterpolatedText('x 10 GB per pack');
expect(wrapper.text()).toMatchSnapshot(); expect(wrapper.text()).toMatchSnapshot();
...@@ -231,11 +184,16 @@ describe('Buy Addons Shared App', () => { ...@@ -231,11 +184,16 @@ describe('Buy Addons Shared App', () => {
}); });
describe('CI Minutes', () => { describe('CI Minutes', () => {
const injectedProps = {
tags: [planTags.CI_1000_MINUTES_PLAN],
i18n: I18N_CI_1000_MINUTES_PLAN,
};
describe('when data is received', () => { describe('when data is received', () => {
beforeEach(async () => { beforeEach(async () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } }); const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } });
const mockApollo = createMockApolloProvider({ plansQueryMock }); const mockApollo = createMockApolloProvider({ plansQueryMock });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
}); });
it('should display the root element', () => { it('should display the root element', () => {
...@@ -252,7 +210,7 @@ describe('Buy Addons Shared App', () => { ...@@ -252,7 +210,7 @@ describe('Buy Addons Shared App', () => {
it('provides the correct props to order summary', () => { it('provides the correct props to order summary', () => {
expect(findOrderSummary().props()).toMatchObject({ expect(findOrderSummary().props()).toMatchObject({
plan: { ...getCiMinutesPlan, isAddon: true }, plan: { ...getCiMinutesPlan, isAddon: true },
title: I18N_CI_MINUTES_TITLE, title: I18N_CI_1000_MINUTES_PLAN.title,
}); });
}); });
}); });
...@@ -262,7 +220,7 @@ describe('Buy Addons Shared App', () => { ...@@ -262,7 +220,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: null }), plansQueryMock: jest.fn().mockResolvedValue({ data: null }),
}); });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -272,7 +230,7 @@ describe('Buy Addons Shared App', () => { ...@@ -272,7 +230,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: null } }), plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: null } }),
}); });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -282,7 +240,7 @@ describe('Buy Addons Shared App', () => { ...@@ -282,7 +240,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: {} } }), plansQueryMock: jest.fn().mockResolvedValue({ data: { plans: {} } }),
}); });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -294,7 +252,7 @@ describe('Buy Addons Shared App', () => { ...@@ -294,7 +252,7 @@ describe('Buy Addons Shared App', () => {
const mockApollo = createMockApolloProvider({ const mockApollo = createMockApolloProvider({
plansQueryMock: jest.fn().mockRejectedValue(new Error('An error happened!')), plansQueryMock: jest.fn().mockRejectedValue(new Error('An error happened!')),
}); });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findRootElement().exists()).toBe(false); expect(findRootElement().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true); expect(findEmptyState().exists()).toBe(true);
...@@ -305,7 +263,7 @@ describe('Buy Addons Shared App', () => { ...@@ -305,7 +263,7 @@ describe('Buy Addons Shared App', () => {
const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } }); const plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } });
it('shows labels correctly for 1 pack', async () => { it('shows labels correctly for 1 pack', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }); const mockApollo = createMockApolloProvider({ plansQueryMock });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText( expect(findQuantityText().text()).toMatchInterpolatedText(
'x 1,000 minutes per pack = 1,000 CI minutes', 'x 1,000 minutes per pack = 1,000 CI minutes',
...@@ -318,7 +276,7 @@ describe('Buy Addons Shared App', () => { ...@@ -318,7 +276,7 @@ describe('Buy Addons Shared App', () => {
it('shows labels correctly for 2 packs', async () => { it('shows labels correctly for 2 packs', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: 2 }); const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: 2 });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText( expect(findQuantityText().text()).toMatchInterpolatedText(
'x 1,000 minutes per pack = 2,000 CI minutes', 'x 1,000 minutes per pack = 2,000 CI minutes',
...@@ -331,7 +289,7 @@ describe('Buy Addons Shared App', () => { ...@@ -331,7 +289,7 @@ describe('Buy Addons Shared App', () => {
it('does not show labels if input is invalid', async () => { it('does not show labels if input is invalid', async () => {
const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: -1 }); const mockApollo = createMockApolloProvider({ plansQueryMock }, { quantity: -1 });
await createComponent(mockApollo, CI_MINUTES_ADDON_PROPS); await createComponent(mockApollo, injectedProps);
expect(findQuantityText().text()).toMatchInterpolatedText('x 1,000 minutes per pack'); expect(findQuantityText().text()).toMatchInterpolatedText('x 1,000 minutes per pack');
expect(wrapper.text()).toMatchSnapshot(); expect(wrapper.text()).toMatchSnapshot();
......
import BuyAddonsApp from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import App from 'ee/subscriptions/buy_minutes/components/app.vue';
import {
CI_MINUTES_PER_PACK,
planTags,
I18N_CI_MINUTES_PRICE_PER_UNIT,
I18N_CI_MINUTES_PRODUCT_LABEL,
I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_DETAILS_FORMULA_WITH_ALERT,
I18N_CI_MINUTES_FORMULA_TOTAL,
i18nCIMinutesSummaryTitle,
I18N_CI_MINUTES_SUMMARY_TOTAL,
I18N_CI_MINUTES_ALERT_TEXT,
I18N_CI_MINUTES_TITLE,
} from 'ee/subscriptions/buy_addons_shared/constants';
describe('Buy Minutes App', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMountExtended(App);
};
const findBuyAddonsApp = () => wrapper.findComponent(BuyAddonsApp);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('passes the correct tags', () => {
expect(findBuyAddonsApp().props('tags')).toEqual([planTags.CI_1000_MINUTES_PLAN]);
});
it('passes the correct config', () => {
expect(findBuyAddonsApp().props('config')).toMatchObject({
alertText: I18N_CI_MINUTES_ALERT_TEXT,
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_CI_MINUTES_FORMULA_TOTAL,
hasExpiration: false,
pricePerUnit: I18N_CI_MINUTES_PRICE_PER_UNIT,
productLabel: I18N_CI_MINUTES_PRODUCT_LABEL,
productUnit: I18N_CI_MINUTES_PRODUCT_UNIT,
quantityPerPack: CI_MINUTES_PER_PACK,
summaryTitle: i18nCIMinutesSummaryTitle,
summaryTotal: I18N_CI_MINUTES_SUMMARY_TOTAL,
title: I18N_CI_MINUTES_TITLE,
});
});
});
import BuyAddonsApp from 'ee/subscriptions/buy_addons_shared/components/app.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import App from 'ee/subscriptions/buy_storage/components/app.vue';
import {
I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_STORAGE_FORMULA_TOTAL,
I18N_DETAILS_FORMULA_WITH_ALERT,
i18nStorageSummaryTitle,
I18N_STORAGE_SUMMARY_TOTAL,
I18N_STORAGE_TITLE,
I18N_STORAGE_PRICE_PER_UNIT,
planTags,
STORAGE_PER_PACK,
} from 'ee/subscriptions/buy_addons_shared/constants';
describe('Buy Storage App', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMountExtended(App);
};
const findBuyAddonsApp = () => wrapper.findComponent(BuyAddonsApp);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('passes the correct tags', () => {
expect(findBuyAddonsApp().props('tags')).toEqual([planTags.STORAGE_PLAN]);
});
it('passes the correct config', () => {
expect(findBuyAddonsApp().props('config')).toMatchObject({
alertText: '',
formula: I18N_DETAILS_FORMULA,
formulaWithAlert: I18N_DETAILS_FORMULA_WITH_ALERT,
formulaTotal: I18N_STORAGE_FORMULA_TOTAL,
hasExpiration: true,
pricePerUnit: I18N_STORAGE_PRICE_PER_UNIT,
productLabel: I18N_STORAGE_PRODUCT_LABEL,
productUnit: I18N_STORAGE_PRODUCT_UNIT,
quantityPerPack: STORAGE_PER_PACK,
summaryTitle: i18nStorageSummaryTitle,
summaryTotal: I18N_STORAGE_SUMMARY_TOTAL,
title: I18N_STORAGE_TITLE,
});
});
});
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