Commit 51b396f7 authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch '350646-add-statistics-card-component' into 'master'

Add statistics card component with tests

See merge request gitlab-org/gitlab!80261
parents f104d053 457f0ebc
import { GlCard } from '@gitlab/ui';
import StatisticsCard from './statistics_card.vue';
export default {
component: StatisticsCard,
title: 'usage_quotas/components/statistics_card',
};
const Template = (_, { argTypes }) => ({
components: { StatisticsCard, GlCard },
props: Object.keys(argTypes),
template: `<gl-card class="gl-w-half">
<statistics-card v-bind="$props">
</statistics-card>
</gl-card>`,
});
export const Default = Template.bind({});
/* eslint-disable @gitlab/require-i18n-strings */
Default.args = {
usageValue: '1,400',
totalValue: '1,500',
description: 'Additional minutes used',
helpLink: 'dummy.com/link',
percentage: 84,
};
export const WithUnits = (_, { argTypes }) => ({
components: { StatisticsCard, GlCard },
props: Object.keys(argTypes),
template: `<gl-card class="gl-w-half">
<statistics-card v-bind="$props">
</statistics-card>
</gl-card>`,
});
WithUnits.args = {
usageValue: '250.0',
usageUnit: 'MiB',
totalValue: '15.0',
totalUnit: 'GiB',
description: 'Storage used',
helpLink: 'dummy.com/link',
percentage: 4,
purchaseButtonLink: 'purchase.com/test',
purchaseButtonText: 'Purchase storage',
};
<script>
import { GlLink, GlIcon, GlButton, GlProgressBar } from '@gitlab/ui';
export default {
name: 'StatisticsCard',
components: { GlLink, GlIcon, GlButton, GlProgressBar },
props: {
usageValue: {
type: String,
required: false,
default: null,
},
usageUnit: {
type: String,
required: false,
default: null,
},
totalValue: {
type: String,
required: false,
default: null,
},
totalUnit: {
type: String,
required: false,
default: null,
},
description: {
type: String,
required: false,
default: null,
},
helpLink: {
type: String,
required: false,
default: null,
},
percentage: {
type: Number,
required: false,
default: null,
},
purchaseButtonLink: {
type: String,
required: false,
default: null,
},
purchaseButtonText: {
type: String,
required: false,
default: null,
},
cssClass: {
type: String,
required: false,
default: null,
},
},
};
</script>
<template>
<div
class="gl-bg-white gl-border-1 gl-border-gray-100 gl-border-solid gl-p-5 gl-rounded-base"
data-testid="container"
:class="cssClass"
>
<div class="gl-display-flex gl-justify-content-space-between gl-mb-3">
<p
v-if="usageValue"
class="gl-font-size-h-display gl-font-weight-bold"
data-testid="denominator"
>
{{ usageValue }}
<span v-if="usageUnit" data-testid="denominator-usage-unit" class="gl-font-lg">{{
usageUnit
}}</span>
<span v-if="totalValue" data-testid="denominator-total">
/
{{ totalValue }}
<span v-if="totalUnit" class="gl-font-lg" data-testid="denominator-total-unit">{{
totalUnit
}}</span>
</span>
</p>
<div>
<gl-button
v-if="purchaseButtonLink && purchaseButtonText"
:href="purchaseButtonLink"
category="primary"
variant="confirm"
>
{{ purchaseButtonText }}
</gl-button>
</div>
</div>
<p v-if="description" class="gl-font-weight-bold gl-mt-3" data-testid="description">
{{ description }}
<gl-link
v-if="helpLink"
:href="helpLink"
target="_blank"
rel="noopener noreferrer nofollow"
class="gl-ml-2"
>
<gl-icon name="question-o" />
</gl-link>
</p>
<gl-progress-bar v-if="percentage" :value="percentage" />
</div>
</template>
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StatisticsCard denominator block renders denominator block with all elements when all props are passed 1`] = `
"<p data-testid=\\"denominator\\" class=\\"gl-font-size-h-display gl-font-weight-bold\\">
1,000
<span data-testid=\\"denominator-usage-unit\\" class=\\"gl-font-lg\\">MiB</span> <span data-testid=\\"denominator-total\\">
/
10,000
<span data-testid=\\"denominator-total-unit\\" class=\\"gl-font-lg\\">MiB</span></span></p>"
`;
import { GlLink, GlButton, GlProgressBar } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import StatisticsCard from 'ee/usage_quotas/components/statistics_card.vue';
describe('StatisticsCard', () => {
let wrapper;
const defaultProps = {
description: 'Dummy text for description',
helpLink: 'http://test.gitlab.com/',
purchaseButtonLink: 'http://gitlab.com/purchase',
purchaseButtonText: 'Purchase more storage',
percentage: 75,
usageValue: '1,000',
usageUnit: 'MiB',
totalValue: '10,000',
totalUnit: 'MiB',
};
const createComponent = (props = {}) => {
wrapper = shallowMount(StatisticsCard, {
propsData: props,
});
};
const findDenominatorBlock = () => wrapper.find('[data-testid="denominator"]');
const findUsageUnitBlock = () => wrapper.find('[data-testid="denominator-usage-unit"]');
const findTotalBlock = () => wrapper.find('[data-testid="denominator-total"]');
const findTotalUnitBlock = () => wrapper.find('[data-testid="denominator-total-unit"]');
const findDescriptionBlock = () => wrapper.find('[data-testid="description"]');
const findPurchaseButton = () => wrapper.findComponent(GlButton);
const findHelpLink = () => wrapper.findComponent(GlLink);
const findProgressBar = () => wrapper.findComponent(GlProgressBar);
it('passes cssClass to container div', () => {
const cssClass = 'awesome-css-class';
createComponent({ cssClass });
expect(wrapper.find('[data-testid="container"]').classes()).toContain(cssClass);
});
describe('denominator block', () => {
it('renders denominator block with all elements when all props are passed', () => {
createComponent(defaultProps);
expect(findDenominatorBlock().html()).toMatchSnapshot();
});
it('hides denominator block if usageValue is not passed', () => {
createComponent({
usageValue: null,
usageUnit: 'minutes',
totalUsage: '1,000',
totalUnit: 'minutes',
});
expect(findDenominatorBlock().exists()).toBe(false);
});
it('does not render usage unit if usageUnit is not passed', () => {
createComponent({
usageValue: '1,000',
usageUnit: null,
totalUsage: '1,000',
totalUnit: 'minutes',
});
expect(findUsageUnitBlock().exists()).toBe(false);
});
it('does not render total block if totalValue is not passed', () => {
createComponent({
usageValue: '1,000',
usageUnit: 'minutes',
totalUsage: null,
totalUnit: 'minutes',
});
expect(findTotalBlock().exists()).toBe(false);
});
it('does not render total unit if totalUnit is not passed', () => {
createComponent({
usageValue: '1,000',
usageUnit: 'minutes',
totalUsage: '1,000',
totalUnit: null,
});
expect(findTotalUnitBlock().exists()).toBe(false);
});
});
describe('description block', () => {
it('does not render description if prop is not passed', () => {
createComponent({ description: null });
expect(findDescriptionBlock().exists()).toBe(false);
});
it('renders help link if description and helpLink props are passed', () => {
const description = 'description value';
const helpLink = 'https://docs.gitlab.com';
createComponent({ description, helpLink });
expect(findDescriptionBlock().text()).toBe(description);
expect(findHelpLink().attributes('href')).toBe(helpLink);
});
it('does not render help link if prop is not passed', () => {
createComponent({ helpLink: null });
expect(wrapper.findComponent(GlLink).exists()).toBe(false);
});
});
describe('purchase button', () => {
const purchaseButtonLink = 'http://gitlab.com/purchase';
const purchaseButtonText = 'Purchase more storage';
it('renders purchase button if purchase link and text props are passed', () => {
createComponent({ purchaseButtonLink, purchaseButtonText });
expect(findPurchaseButton().text()).toBe(purchaseButtonText);
expect(findPurchaseButton().attributes('href')).toBe(purchaseButtonLink);
});
it('does not render purchase button if purchase link is not passed', () => {
createComponent({ purchaseButtonText });
expect(findPurchaseButton().exists()).toBe(false);
});
it('does not render purchase button if purchase text is not passed', () => {
createComponent({ purchaseButtonLink });
expect(findPurchaseButton().exists()).toBe(false);
});
});
describe('progress bar', () => {
it('does not render progress bar if prop is not passed', () => {
createComponent({ percentage: null });
expect(wrapper.findComponent(GlProgressBar).exists()).toBe(false);
});
it('renders progress bar if prop is passed', () => {
const percentage = 99;
createComponent({ percentage });
expect(findProgressBar().exists()).toBe(true);
expect(findProgressBar().attributes('value')).toBe(String(percentage));
});
});
});
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