Commit 5d676eb1 authored by Mark Florian's avatar Mark Florian

Merge branch 'ag/333698-tax-and-subtotal-ci-min' into 'master'

Display subtotal and tax line in CI Minutes Purchase

See merge request gitlab-org/gitlab!67479
parents 37c947e4 1fa181bd
<script> <script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import formattingMixins from 'ee/subscriptions/new/formatting_mixins'; import formattingMixins from 'ee/subscriptions/new/formatting_mixins';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
export default { export default {
components: {
GlLink,
GlSprintf,
},
mixins: [formattingMixins], mixins: [formattingMixins],
props: { props: {
vat: { vat: {
...@@ -48,6 +53,15 @@ export default { ...@@ -48,6 +53,15 @@ export default {
endDate() { endDate() {
return this.startDate.setFullYear(this.startDate.getFullYear() + 1); return this.startDate.setFullYear(this.startDate.getFullYear() + 1);
}, },
hasPositiveQuantity() {
return this.quantity > 0;
},
taxAmount() {
return this.taxRate ? this.formatAmount(this.vat, this.quantity > 0) : '';
},
taxLine() {
return `${this.$options.i18n.tax} ${this.$options.i18n.taxNote}`;
},
}, },
i18n: { i18n: {
selectedPlanText: s__('Checkout|%{selectedPlanText} plan'), selectedPlanText: s__('Checkout|%{selectedPlanText} plan'),
...@@ -56,29 +70,32 @@ export default { ...@@ -56,29 +70,32 @@ export default {
dates: s__('Checkout|%{startDate} - %{endDate}'), dates: s__('Checkout|%{startDate} - %{endDate}'),
subtotal: s__('Checkout|Subtotal'), subtotal: s__('Checkout|Subtotal'),
tax: s__('Checkout|Tax'), tax: s__('Checkout|Tax'),
taxNote: s__('Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})'),
total: s__('Checkout|Total'), total: s__('Checkout|Total'),
}, },
}; };
</script> </script>
<template> <template>
<div> <div>
<div class="d-flex justify-content-between bold gl-mt-3 gl-mb-3"> <div
class="gl-display-flex gl-justify-content-space-between gl-font-weight-bold gl-mt-3 gl-mb-3"
>
<div data-testid="selected-plan"> <div data-testid="selected-plan">
{{ sprintf($options.i18n.selectedPlanText, { selectedPlanText }) }} {{ sprintf($options.i18n.selectedPlanText, { selectedPlanText }) }}
<span v-if="quantity" data-testid="quantity">{{ <span v-if="quantity" data-testid="quantity">{{
sprintf($options.i18n.quantity, { quantity }) sprintf($options.i18n.quantity, { quantity })
}}</span> }}</span>
</div> </div>
<div data-testid="amount">{{ formatAmount(totalExVat, quantity > 0) }}</div> <div data-testid="amount">{{ formatAmount(totalExVat, hasPositiveQuantity) }}</div>
</div> </div>
<div class="text-secondary" data-testid="price-per-unit"> <div class="gl-text-gray-500" data-testid="price-per-unit">
{{ {{
sprintf($options.i18n.pricePerUnitPerYear, { sprintf($options.i18n.pricePerUnitPerYear, {
selectedPlanPrice: selectedPlanPrice.toLocaleString(), selectedPlanPrice: selectedPlanPrice.toLocaleString(),
}) })
}} }}
</div> </div>
<div v-if="purchaseHasExpiration" class="text-secondary" data-testid="subscription-period"> <div v-if="purchaseHasExpiration" class="gl-text-gray-500" data-testid="subscription-period">
{{ {{
sprintf($options.i18n.dates, { sprintf($options.i18n.dates, {
startDate: formatDate(startDate), startDate: formatDate(startDate),
...@@ -86,21 +103,35 @@ export default { ...@@ -86,21 +103,35 @@ export default {
}) })
}} }}
</div> </div>
<div v-if="taxRate"> <div>
<div class="border-bottom gl-mt-3 gl-mb-3"></div> <div class="border-bottom gl-mt-3 gl-mb-3"></div>
<div class="d-flex justify-content-between text-secondary"> <div class="gl-display-flex gl-justify-content-space-between gl-text-gray-500">
<div>{{ $options.i18n.subtotal }}</div> <div>{{ $options.i18n.subtotal }}</div>
<div data-testid="total-ex-vat">{{ formatAmount(totalExVat, quantity > 0) }}</div> <div data-testid="total-ex-vat">{{ formatAmount(totalExVat, hasPositiveQuantity) }}</div>
</div> </div>
<div class="d-flex justify-content-between text-secondary"> <div class="gl-display-flex gl-justify-content-space-between gl-text-gray-500">
<div>{{ $options.i18n.tax }}</div> <div>
<div data-testid="vat">{{ formatAmount(vat, quantity > 0) }}</div> <div data-testid="vat-info-line">
<gl-sprintf :message="taxLine">
<template #link="{ content }">
<gl-link
class="gl-text-decoration-underline gl-text-gray-500"
href="https://about.gitlab.com/handbook/tax/#indirect-taxes-management"
target="_blank"
data-testid="vat-help-link"
>{{ content }}</gl-link
>
</template>
</gl-sprintf>
</div>
</div>
<div data-testid="vat">{{ taxAmount }}</div>
</div> </div>
</div> </div>
<div class="border-bottom gl-mt-3 gl-mb-3"></div> <div class="gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mt-3 gl-mb-3"></div>
<div class="d-flex justify-content-between bold gl-font-lg"> <div class="gl-display-flex gl-justify-content-space-between gl-font-weight-bold gl-font-lg">
<div>{{ $options.i18n.total }}</div> <div>{{ $options.i18n.total }}</div>
<div data-itestid="total-amount">{{ formatAmount(totalAmount, quantity > 0) }}</div> <div data-testid="total-amount">{{ formatAmount(totalAmount, hasPositiveQuantity) }}</div>
</div> </div>
</div> </div>
</template> </template>
import { shallowMount } from '@vue/test-utils'; import { GlSprintf } from '@gitlab/ui';
import SummaryDetails from 'ee/subscriptions/buy_minutes/components/order_summary/summary_details.vue'; import SummaryDetails from 'ee/subscriptions/buy_minutes/components/order_summary/summary_details.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('SummaryDetails', () => { describe('SummaryDetails', () => {
let wrapper; let wrapper;
const createComponent = (props = {}) => { const createComponent = (props = {}) => {
return shallowMount(SummaryDetails, { return shallowMountExtended(SummaryDetails, {
propsData: { propsData: {
vat: 8, vat: 8,
totalExVat: 10, totalExVat: 10,
...@@ -15,13 +16,19 @@ describe('SummaryDetails', () => { ...@@ -15,13 +16,19 @@ describe('SummaryDetails', () => {
quantity: 1, quantity: 1,
...props, ...props,
}, },
stubs: {
GlSprintf,
},
}); });
}; };
const findQuantity = () => wrapper.find('[data-testid="quantity"]'); const findQuantity = () => wrapper.findByTestId('quantity');
const findSubscriptionPeriod = () => wrapper.find('[data-testid="subscription-period"]'); const findSubscriptionPeriod = () => wrapper.findByTestId('subscription-period');
const findTotalExVat = () => wrapper.find('[data-testid="total-ex-vat"]'); const findTotalAmount = () => wrapper.findByTestId('total-amount');
const findVat = () => wrapper.find('[data-testid="vat"]'); const findTotalExVat = () => wrapper.findByTestId('total-ex-vat');
const findVat = () => wrapper.findByTestId('vat');
const findVatHelpLink = () => wrapper.findByTestId('vat-help-link');
const findVatInfoLine = () => wrapper.findByTestId('vat-info-line');
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -33,13 +40,29 @@ describe('SummaryDetails', () => { ...@@ -33,13 +40,29 @@ describe('SummaryDetails', () => {
}); });
it('renders the plan name', () => { it('renders the plan name', () => {
expect(wrapper.find('[data-testid="selected-plan"]').text()).toMatchInterpolatedText( expect(wrapper.findByTestId('selected-plan').text()).toMatchInterpolatedText(
'Test plan (x1)', 'Test plan (x1)',
); );
}); });
it('renders the price per unit', () => { it('renders the price per unit', () => {
expect(wrapper.find('[data-testid="price-per-unit"]').text()).toBe('$10 per pack per year'); expect(wrapper.findByTestId('price-per-unit').text()).toBe('$10 per pack per year');
});
it('displays the total amount', () => {
expect(findTotalAmount().text()).toBe('$10');
});
it('displays a help link', () => {
expect(findVatHelpLink().attributes('href')).toBe(
'https://about.gitlab.com/handbook/tax/#indirect-taxes-management',
);
});
it('displays an info text', () => {
expect(findVatInfoLine().text()).toMatchInterpolatedText(
'Tax (may be charged upon purchase)',
);
}); });
}); });
...@@ -60,7 +83,7 @@ describe('SummaryDetails', () => { ...@@ -60,7 +83,7 @@ describe('SummaryDetails', () => {
}); });
it('does not render quantity', () => { it('does not render quantity', () => {
expect(wrapper.find('[data-testid="quantity"]').exists()).toBe(false); expect(wrapper.findByTestId('quantity').exists()).toBe(false);
}); });
}); });
...@@ -97,6 +120,18 @@ describe('SummaryDetails', () => { ...@@ -97,6 +120,18 @@ describe('SummaryDetails', () => {
expect(findVat().isVisible()).toBe(true); expect(findVat().isVisible()).toBe(true);
expect(findVat().text()).toBe('$8'); expect(findVat().text()).toBe('$8');
}); });
it('displays a help link', () => {
expect(findVatHelpLink().attributes('href')).toBe(
'https://about.gitlab.com/handbook/tax/#indirect-taxes-management',
);
});
it('displays an info text', () => {
expect(findVatInfoLine().text()).toMatchInterpolatedText(
'Tax (may be charged upon purchase)',
);
});
}); });
describe('when tax rate is not applied', () => { describe('when tax rate is not applied', () => {
...@@ -104,9 +139,8 @@ describe('SummaryDetails', () => { ...@@ -104,9 +139,8 @@ describe('SummaryDetails', () => {
wrapper = createComponent(); wrapper = createComponent();
}); });
it('does not render tax fields', () => { it('displays the vat amount with a stopgap', () => {
expect(findTotalExVat().exists()).toBe(false); expect(findVat().text()).toBe('');
expect(findVat().exists()).toBe(false);
}); });
}); });
}); });
...@@ -6497,6 +6497,9 @@ msgstr "" ...@@ -6497,6 +6497,9 @@ msgstr ""
msgid "Checkout|%{totalCiMinutes} CI minutes" msgid "Checkout|%{totalCiMinutes} CI minutes"
msgstr "" msgstr ""
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
msgid "Checkout|(x%{numberOfUsers})" msgid "Checkout|(x%{numberOfUsers})"
msgstr "" msgstr ""
......
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