Commit 2ca210f2 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch 'dz/327889-use-subscription-details-in-storage' into 'master'

Parametrize subscription details in storage purchase

See merge request gitlab-org/gitlab!70110
parents 7a63d8e1 579b644f
......@@ -6,10 +6,9 @@ import PaymentMethod from 'ee/vue_shared/purchase_flow/components/checkout/payme
import { GENERAL_ERROR_MESSAGE } from 'ee/vue_shared/purchase_flow/constants';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import AddonPurchaseDetails from './checkout/addon_purchase_details.vue';
export default {
components: { AddonPurchaseDetails, BillingAddress, PaymentMethod, ConfirmOrder },
components: { BillingAddress, PaymentMethod, ConfirmOrder },
props: {
plan: {
type: Object,
......@@ -42,7 +41,7 @@ export default {
<div class="checkout gl-display-flex gl-flex-direction-column gl-align-items-center">
<div class="flash-container"></div>
<h2 class="gl-align-self-start gl-mt-6 gl-mb-7 gl-mb-lg-5">{{ $options.i18n.checkout }}</h2>
<addon-purchase-details :plan="plan" />
<slot name="purchase-details"></slot>
<billing-address />
<payment-method />
<confirm-order />
......
<script>
import { GlAlert, GlFormInput, GlSprintf } from '@gitlab/ui';
import { CI_MINUTES_PER_PACK } from 'ee/subscriptions/buy_addons_shared/constants';
import { GlAlert, GlFormInput } from '@gitlab/ui';
import { STEPS } from 'ee/subscriptions/constants';
import updateState from 'ee/subscriptions/graphql/mutations/update_state.mutation.graphql';
import stateQuery from 'ee/subscriptions/graphql/queries/state.query.graphql';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { GENERAL_ERROR_MESSAGE } from 'ee/vue_shared/purchase_flow/constants';
import createFlash from '~/flash';
import { n__, s__, sprintf, formatNumber } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import { I18N_DETAILS_STEP_TITLE, I18N_DETAILS_NEXT_STEP_BUTTON_TEXT } from '../../constants';
export default {
name: 'AddonPurchaseDetails',
components: {
GlAlert,
GlFormInput,
GlSprintf,
Step,
},
directives: {
autofocusonshow,
},
props: {
productLabel: {
type: String,
required: true,
},
quantityPerPack: {
type: Number,
required: true,
},
showAlert: {
type: Boolean,
required: false,
},
alertText: {
type: String,
required: false,
default: '',
},
},
apollo: {
quantity: {
query: stateQuery,
......@@ -41,26 +58,8 @@ export default {
isValid() {
return this.quantity > 0;
},
totalCiMinutes() {
return this.quantity * CI_MINUTES_PER_PACK;
},
summaryCiMinutesQuantityText() {
return n__('Checkout|%d CI minute pack', 'Checkout|%d CI minute packs', this.quantity);
},
ciMinutesQuantityText() {
return sprintf(
n__(
'Checkout|%{totalCiMinutes} CI minute',
'Checkout|%{totalCiMinutes} CI minutes',
this.totalCiMinutes,
),
{ totalCiMinutes: formatNumber(this.totalCiMinutes) },
);
},
summaryCiMinutesTotal() {
return sprintf(this.$options.i18n.summaryCiMinutesTotal, {
quantity: formatNumber(this.totalCiMinutes),
});
totalUnits() {
return this.quantity * this.quantityPerPack;
},
},
methods: {
......@@ -78,15 +77,8 @@ export default {
},
},
i18n: {
stepTitle: s__('Checkout|Purchase details'),
nextStepButtonText: s__('Checkout|Continue to billing'),
ciMinutesLabel: s__('Checkout|CI minute pack'),
ciMinutesAlertText: 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.",
),
ciMinutesPacksQuantityFormula: s__('Checkout|x 1,000 minutes per pack = %{strong}'),
ciMinutesQuantityText: s__('Checkout|%{totalCiMinutes} CI minutes'),
summaryCiMinutesTotal: s__('Checkout|Total minutes: %{quantity}'),
stepTitle: I18N_DETAILS_STEP_TITLE,
nextStepButtonText: I18N_DETAILS_NEXT_STEP_BUTTON_TEXT,
},
stepId: STEPS[0].id,
};
......@@ -100,11 +92,11 @@ export default {
:next-step-button-text="$options.i18n.nextStepButtonText"
>
<template #body>
<gl-alert variant="info" class="gl-mb-3" :dismissible="false">
{{ $options.i18n.ciMinutesAlertText }}
<gl-alert v-if="showAlert && alertText" variant="info" class="gl-mb-3" :dismissible="false">
{{ alertText }}
</gl-alert>
<label class="gl-mt-3" for="quantity" data-testid="product-label">
{{ $options.i18n.ciMinutesLabel }}
{{ productLabel }}
</label>
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center gl-mb-6">
<gl-form-input
......@@ -116,20 +108,13 @@ export default {
data-qa-selector="quantity"
class="gl-w-15"
/>
<div class="gl-ml-3" data-testid="ci-minutes-quantity-text">
<gl-sprintf :message="$options.i18n.ciMinutesPacksQuantityFormula">
<template #strong>
<strong>{{ ciMinutesQuantityText }}</strong>
</template>
</gl-sprintf>
<div class="gl-ml-3" data-testid="addon-quantity-text">
<slot name="formula" :quantity="totalUnits"></slot>
</div>
</div>
</template>
<template #summary>
<strong ref="summary-line-1">
{{ summaryCiMinutesQuantityText }}
</strong>
<div ref="summary-line-3">{{ summaryCiMinutesTotal }}</div>
<slot name="summary-label" :quantity="quantity"></slot>
</template>
</step>
</template>
import { s__, n__ } from '~/locale';
/* eslint-disable @gitlab/require-i18n-strings */
export const planTags = {
CI_1000_MINUTES_PLAN: 'CI_1000_MINUTES_PLAN',
......@@ -8,3 +10,25 @@ export const CUSTOMER_CLIENT = 'customerClient';
export const GITLAB_CLIENT = 'gitlabClient';
export const CI_MINUTES_PER_PACK = 1000;
export const STORAGE_PER_PACK = 10;
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_FORMULA_TOTAL = s__('Checkout|%{totalCiMinutes} 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_STORAGE_PRODUCT_LABEL = s__('Checkout|Storage packs');
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_DETAILS_STEP_TITLE = s__('Checkout|Purchase details');
export const I18N_DETAILS_NEXT_STEP_BUTTON_TEXT = s__('Checkout|Continue to billing');
export const I18N_DETAILS_FORMULA = s__('Checkout|x %{quantity} %{units} per pack =');
......@@ -11,9 +11,10 @@ function arrayToGraphqlArray(arr, typename) {
}
export function writeInitialDataToApolloCache(apolloProvider, dataset) {
const { groupData, namespaceId, redirectAfterSuccess } = dataset;
const { groupData, namespaceId, redirectAfterSuccess, subscriptionQuantity } = dataset;
// eslint-disable-next-line @gitlab/require-i18n-strings
const namespaces = arrayToGraphqlArray(JSON.parse(groupData), 'Namespace');
const quantity = subscriptionQuantity || 1;
apolloProvider.clients.defaultClient.cache.writeQuery({
query: stateQuery,
......@@ -25,7 +26,7 @@ export function writeInitialDataToApolloCache(apolloProvider, dataset) {
namespaces,
redirectAfterSuccess,
subscription: {
quantity: 1,
quantity,
namespaceId,
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Subscription',
......
......@@ -4,9 +4,23 @@ import { GlEmptyState } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import StepOrderApp from 'ee/vue_shared/purchase_flow/components/step_order_app.vue';
import { ERROR_FETCHING_DATA_HEADER, ERROR_FETCHING_DATA_DESCRIPTION } from '~/ensure_data';
import { sprintf, formatNumber } from '~/locale';
import Checkout from '../../buy_addons_shared/components/checkout.vue';
import AddonPurchaseDetails from '../../buy_addons_shared/components/checkout/addon_purchase_details.vue';
import OrderSummary from '../../buy_addons_shared/components/order_summary.vue';
import { planTags, CUSTOMER_CLIENT } from '../../buy_addons_shared/constants';
import {
I18N_CI_MINUTES_PRODUCT_LABEL,
I18N_CI_MINUTES_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_CI_MINUTES_FORMULA_TOTAL,
i18nCIMinutesSummaryTitle,
I18N_CI_MINUTES_SUMMARY_TOTAL,
I18N_CI_MINUTES_ALERT_TEXT,
planTags,
CUSTOMER_CLIENT,
CI_MINUTES_PER_PACK,
} from '../../buy_addons_shared/constants';
import plansQuery from '../../graphql/queries/plans.customer.query.graphql';
export default {
......@@ -16,17 +30,47 @@ export default {
GlEmptyState,
OrderSummary,
StepOrderApp,
AddonPurchaseDetails,
},
i18n: {
ERROR_FETCHING_DATA_HEADER,
ERROR_FETCHING_DATA_DESCRIPTION,
productLabel: I18N_CI_MINUTES_PRODUCT_LABEL,
productUnit: I18N_CI_MINUTES_PRODUCT_UNIT,
formula: I18N_DETAILS_FORMULA,
formulaTotal: I18N_CI_MINUTES_FORMULA_TOTAL,
summaryTitle: i18nCIMinutesSummaryTitle,
summaryTotal: I18N_CI_MINUTES_SUMMARY_TOTAL,
alertText: I18N_CI_MINUTES_ALERT_TEXT,
},
CI_MINUTES_PER_PACK,
emptySvg,
data() {
return {
hasError: false,
};
},
computed: {
formulaText() {
return sprintf(this.$options.i18n.formula, {
quantity: formatNumber(CI_MINUTES_PER_PACK),
units: this.$options.i18n.productUnit,
});
},
},
methods: {
formulaTotal(quantity) {
return sprintf(this.$options.i18n.formulaTotal, { totalCiMinutes: formatNumber(quantity) });
},
summaryTitle(quantity) {
return sprintf(this.$options.i18n.summaryTitle(quantity), { quantity });
},
summaryTotal(quantity) {
return sprintf(this.$options.i18n.summaryTotal, {
quantity: formatNumber(quantity * CI_MINUTES_PER_PACK),
});
},
},
apollo: {
plans: {
client: CUSTOMER_CLIENT,
......@@ -59,7 +103,27 @@ export default {
/>
<step-order-app v-else-if="!$apollo.loading">
<template #checkout>
<checkout :plan="plans[0]" />
<checkout :plan="plans[0]">
<template #purchase-details>
<addon-purchase-details
:product-label="$options.i18n.productLabel"
:quantity-per-pack="$options.CI_MINUTES_PER_PACK"
:show-alert="true"
:alert-text="$options.i18n.alertText"
>
<template #formula="{ quantity }">
{{ formulaText }}
<strong>{{ formulaTotal(quantity) }}</strong>
</template>
<template #summary-label="{ quantity }">
<strong data-testid="summary-label">
{{ summaryTitle(quantity) }}
</strong>
<p class="gl-mb-0" data-testid="summary-total">{{ summaryTotal(quantity) }}</p>
</template>
</addon-purchase-details>
</template>
</checkout>
</template>
<template #order-summary>
<order-summary :plan="plans[0]" />
......
......@@ -4,9 +4,21 @@ import { GlEmptyState } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import StepOrderApp from 'ee/vue_shared/purchase_flow/components/step_order_app.vue';
import { ERROR_FETCHING_DATA_HEADER, ERROR_FETCHING_DATA_DESCRIPTION } from '~/ensure_data';
import { sprintf, formatNumber } from '~/locale';
import Checkout from '../../buy_addons_shared/components/checkout.vue';
import AddonPurchaseDetails from '../../buy_addons_shared/components/checkout/addon_purchase_details.vue';
import OrderSummary from '../../buy_addons_shared/components/order_summary.vue';
import { planTags, CUSTOMER_CLIENT } from '../../buy_addons_shared/constants';
import {
I18N_STORAGE_PRODUCT_LABEL,
I18N_STORAGE_PRODUCT_UNIT,
I18N_DETAILS_FORMULA,
I18N_STORAGE_FORMULA_TOTAL,
i18nStorageSummaryTitle,
I18N_STORAGE_SUMMARY_TOTAL,
planTags,
CUSTOMER_CLIENT,
STORAGE_PER_PACK,
} from '../../buy_addons_shared/constants';
import plansQuery from '../../graphql/queries/plans.customer.query.graphql';
export default {
......@@ -16,17 +28,46 @@ export default {
GlEmptyState,
OrderSummary,
StepOrderApp,
AddonPurchaseDetails,
},
i18n: {
ERROR_FETCHING_DATA_HEADER,
ERROR_FETCHING_DATA_DESCRIPTION,
productLabel: I18N_STORAGE_PRODUCT_LABEL,
productUnit: I18N_STORAGE_PRODUCT_UNIT,
formula: I18N_DETAILS_FORMULA,
formulaTotal: I18N_STORAGE_FORMULA_TOTAL,
summaryTitle: i18nStorageSummaryTitle,
summaryTotal: I18N_STORAGE_SUMMARY_TOTAL,
},
emptySvg,
STORAGE_PER_PACK,
data() {
return {
hasError: false,
};
},
computed: {
formulaText() {
return sprintf(this.$options.i18n.formula, {
quantity: formatNumber(STORAGE_PER_PACK),
units: this.$options.i18n.productUnit,
});
},
},
methods: {
formulaTotal(quantity) {
return sprintf(this.$options.i18n.formulaTotal, { quantity: formatNumber(quantity) });
},
summaryTitle(quantity) {
return sprintf(this.$options.i18n.summaryTitle(quantity), { quantity });
},
summaryTotal(quantity) {
return sprintf(this.$options.i18n.summaryTotal, {
quantity: formatNumber(quantity * STORAGE_PER_PACK),
});
},
},
apollo: {
plans: {
client: CUSTOMER_CLIENT,
......@@ -59,7 +100,25 @@ export default {
/>
<step-order-app v-else-if="!$apollo.loading">
<template #checkout>
<checkout :plan="plans[0]" />
<checkout :plan="plans[0]">
<template #purchase-details>
<addon-purchase-details
:product-label="$options.i18n.productLabel"
:quantity-per-pack="$options.STORAGE_PER_PACK"
>
<template #formula="{ quantity }">
{{ formulaText }}
<strong>{{ formulaTotal(quantity) }}</strong>
</template>
<template #summary-label="{ quantity }">
<strong data-testid="summary-label">
{{ summaryTitle(quantity) }}
</strong>
<p class="gl-mb-0">{{ summaryTotal(quantity) }}</p>
</template>
</addon-purchase-details>
</template>
</checkout>
</template>
<template #order-summary>
<order-summary :plan="plans[0]" />
......
......@@ -4,7 +4,6 @@ import { merge } from 'lodash';
import VueApollo from 'vue-apollo';
import AddonPurchaseDetails from 'ee/subscriptions/buy_addons_shared/components/checkout/addon_purchase_details.vue';
import subscriptionsResolvers 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 Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import purchaseFlowResolvers from 'ee/vue_shared/purchase_flow/graphql/resolvers';
......@@ -29,7 +28,7 @@ describe('AddonPurchaseDetails', () => {
return mockApollo;
};
const createComponent = (stateData = {}) => {
const createComponent = (stateData = {}, props = {}) => {
const apolloProvider = createMockApolloProvider(stateData);
wrapper = mountExtended(AddonPurchaseDetails, {
localVue,
......@@ -37,14 +36,20 @@ describe('AddonPurchaseDetails', () => {
stubs: {
Step,
},
propsData: {
productLabel: 'CI minute pack',
quantityPerPack: 1000,
packsFormula: 'x %{packQuantity} minutes per pack = %{strong}',
quantityText: '%{quantity} CI minutes',
totalPurchase: 'Total minutes: %{quantity}',
...props,
},
});
};
const findQuantity = () => wrapper.findComponent({ ref: 'quantity' });
const findGlAlert = () => wrapper.findComponent(GlAlert);
const findCiMinutesQuantityText = () => wrapper.findByTestId('ci-minutes-quantity-text');
const findProductLabel = () => wrapper.findByTestId('product-label');
const findSummaryLabel = () => wrapper.findComponent({ ref: 'summary-line-1' });
const isStepValid = () => wrapper.findComponent(Step).props('isValid');
beforeEach(() => {
......@@ -59,17 +64,8 @@ describe('AddonPurchaseDetails', () => {
expect(findQuantity().attributes('min')).toBe('1');
});
it('displays the alert', () => {
expect(findGlAlert().isVisible()).toBe(true);
expect(findGlAlert().text()).toMatchInterpolatedText(
AddonPurchaseDetails.i18n.ciMinutesAlertText,
);
});
it('displays the total CI minutes text', async () => {
expect(findCiMinutesQuantityText().text()).toMatchInterpolatedText(
'x 1,000 minutes per pack = 1,000 CI minutes',
);
it('shows the correct product label', () => {
expect(findProductLabel().text()).toBe('CI minute pack');
});
it('is valid', () => {
......@@ -84,33 +80,25 @@ describe('AddonPurchaseDetails', () => {
expect(isStepValid()).toBe(false);
});
describe('labels', () => {
describe('when quantity is 1', () => {
it('shows the correct product label', () => {
expect(findProductLabel().text()).toBe('CI minute pack');
});
it('shows the correct summary label', () => {
createComponent({ activeStep: STEPS[1] });
expect(findSummaryLabel().text()).toBe('1 CI minute pack');
});
describe('alert', () => {
it('is hidden if no props passed', () => {
expect(findGlAlert().exists()).toBe(false);
});
describe('when quantity is more than 1', () => {
const stateData = { subscription: { namespaceId: 483, quantity: 2 } };
it('shows the correct product label', () => {
createComponent(stateData);
expect(findProductLabel().text()).toBe('CI minute pack');
});
it('is hidden when props are set to false', () => {
createComponent({}, { showAlert: false, alertText: 'Alert text about your purchase' });
expect(findGlAlert().exists()).toBe(false);
});
it('shows the correct summary label', () => {
createComponent({ ...stateData, activeStep: STEPS[1] });
it('is hidden when alertText prop is missing', () => {
createComponent({}, { showAlert: true });
expect(findGlAlert().exists()).toBe(false);
});
expect(findSummaryLabel().text()).toBe('2 CI minute packs');
});
it('is shown', () => {
createComponent({}, { showAlert: true, alertText: 'Alert text about your purchase' });
expect(findGlAlert().isVisible()).toBe(true);
expect(findGlAlert().text()).toMatchInterpolatedText('Alert text about your purchase');
});
});
});
import { GlEmptyState } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
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 App from 'ee/subscriptions/buy_minutes/components/app.vue';
import StepOrderApp from 'ee/vue_shared/purchase_flow/components/step_order_app.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { planTags } from '../../../../../app/assets/javascripts/subscriptions/buy_addons_shared/constants';
import { createMockApolloProvider } from '../spec_helper';
......@@ -14,13 +17,21 @@ describe('App', () => {
let wrapper;
function createComponent(apolloProvider) {
return shallowMount(App, {
return shallowMountExtended(App, {
localVue,
propsData: { plan: planTags.CI_1000_MINUTES_PLAN },
apolloProvider,
stubs: {
Checkout,
AddonPurchaseDetails,
},
});
}
const findQuantityText = () => wrapper.findByTestId('addon-quantity-text');
const findSummaryLabel = () => wrapper.findByTestId('summary-label');
const findSummaryTotal = () => wrapper.findByTestId('summary-total');
afterEach(() => {
wrapper.destroy();
});
......@@ -83,4 +94,40 @@ describe('App', () => {
expect(wrapper.findComponent(GlEmptyState).exists()).toBe(true);
});
});
describe('labels', () => {
it('are shown correctly for 1 pack', async () => {
const mockApollo = createMockApolloProvider();
wrapper = createComponent(mockApollo);
await waitForPromises();
expect(findQuantityText().exists()).toBe(true);
expect(findQuantityText().text()).toMatchInterpolatedText(
'x 1,000 minutes per pack = 1,000 CI minutes',
);
expect(findSummaryLabel().exists()).toBe(true);
expect(findSummaryLabel().text()).toBe('1 CI minute pack');
expect(findSummaryTotal().exists()).toBe(true);
expect(findSummaryTotal().text()).toBe('Total minutes: 1,000');
});
it('are shown correctly for 2 packs', async () => {
const mockApollo = createMockApolloProvider({}, { quantity: 2 });
wrapper = createComponent(mockApollo);
await waitForPromises();
expect(findQuantityText().exists()).toBe(true);
expect(findQuantityText().text()).toMatchInterpolatedText(
'x 1,000 minutes per pack = 2,000 CI minutes',
);
expect(findSummaryLabel().exists()).toBe(true);
expect(findSummaryLabel().text()).toBe('2 CI minute packs');
expect(findSummaryTotal().exists()).toBe(true);
expect(findSummaryTotal().text()).toBe('Total minutes: 2,000');
});
});
});
......@@ -21,6 +21,12 @@ export const mockNewUser = 'false';
export const mockFullName = 'John Admin';
export const mockSetupForCompany = 'true';
export const mockDefaultCache = {
groupData: '[]',
namespaceId: 'My Namespace',
redirectAfterSuccess: '/',
};
export const stateData = {
namespaces: [],
subscription: {
......
import VueApollo from 'vue-apollo';
import { writeInitialDataToApolloCache } from 'ee/subscriptions/buy_addons_shared/utils';
import plansQuery from 'ee/subscriptions/graphql/queries/plans.customer.query.graphql';
import { createMockClient } from 'helpers/mock_apollo_helper';
import { mockCiMinutesPlans } from './mock_data';
import { mockCiMinutesPlans, mockDefaultCache } from './mock_data';
export function createMockApolloProvider(mockResponses = {}) {
export function createMockApolloProvider(mockResponses = {}, dataset = {}) {
const {
plansQueryMock = jest.fn().mockResolvedValue({ data: { plans: mockCiMinutesPlans } }),
} = mockResponses;
const { quantity } = dataset;
const mockDefaultClient = createMockClient();
const mockCustomerClient = createMockClient([[plansQuery, plansQueryMock]]);
return new VueApollo({
const apolloProvider = new VueApollo({
defaultClient: mockDefaultClient,
clients: { customerClient: mockCustomerClient },
});
writeInitialDataToApolloCache(apolloProvider, {
...mockDefaultCache,
subscriptionQuantity: quantity,
});
return apolloProvider;
}
......@@ -6569,17 +6569,20 @@ msgstr ""
msgid "Checkout|%{name}'s GitLab subscription"
msgstr ""
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
msgstr[0] ""
msgstr[1] ""
msgid "Checkout|%{selectedPlanText} plan"
msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
msgid "Checkout|%{totalCiMinutes} CI minute"
msgid_plural "Checkout|%{totalCiMinutes} CI minutes"
msgstr[0] ""
msgstr[1] ""
msgid "Checkout|%{totalCiMinutes} CI minutes"
msgstr ""
......@@ -6655,6 +6658,9 @@ msgstr ""
msgid "Checkout|Failed to register credit card. Please try again."
msgstr ""
msgid "Checkout|GB"
msgstr ""
msgid "Checkout|GitLab group"
msgstr ""
......@@ -6691,6 +6697,9 @@ msgstr ""
msgid "Checkout|State"
msgstr ""
msgid "Checkout|Storage packs"
msgstr ""
msgid "Checkout|Street address"
msgstr ""
......@@ -6712,6 +6721,9 @@ msgstr ""
msgid "Checkout|Total minutes: %{quantity}"
msgstr ""
msgid "Checkout|Total storage: %{quantity} GB"
msgstr ""
msgid "Checkout|Users"
msgstr ""
......@@ -6730,7 +6742,10 @@ msgstr ""
msgid "Checkout|company or team"
msgstr ""
msgid "Checkout|x 1,000 minutes per pack = %{strong}"
msgid "Checkout|minutes"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""
msgid "Cherry-pick this commit"
......
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