diff options
Diffstat (limited to 'spec/frontend/analytics')
4 files changed, 211 insertions, 0 deletions
diff --git a/spec/frontend/analytics/instance_statistics/components/app_spec.js b/spec/frontend/analytics/instance_statistics/components/app_spec.js new file mode 100644 index 00000000000..242621dc40c --- /dev/null +++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js @@ -0,0 +1,24 @@ +import { shallowMount } from '@vue/test-utils'; +import InstanceStatisticsApp from '~/analytics/instance_statistics/components/app.vue'; +import InstanceCounts from '~/analytics/instance_statistics/components//instance_counts.vue'; + +describe('InstanceStatisticsApp', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(InstanceStatisticsApp); + }; + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('displays the instance counts component', () => { + expect(wrapper.find(InstanceCounts).exists()).toBe(true); + }); +}); diff --git a/spec/frontend/analytics/instance_statistics/components/instance_counts_spec.js b/spec/frontend/analytics/instance_statistics/components/instance_counts_spec.js new file mode 100644 index 00000000000..2274f4c3fde --- /dev/null +++ b/spec/frontend/analytics/instance_statistics/components/instance_counts_spec.js @@ -0,0 +1,54 @@ +import { shallowMount } from '@vue/test-utils'; +import InstanceCounts from '~/analytics/instance_statistics/components/instance_counts.vue'; +import MetricCard from '~/analytics/shared/components/metric_card.vue'; +import countsMockData from '../mock_data'; + +describe('InstanceCounts', () => { + let wrapper; + + const createComponent = ({ loading = false, data = {} } = {}) => { + const $apollo = { + queries: { + counts: { + loading, + }, + }, + }; + + wrapper = shallowMount(InstanceCounts, { + mocks: { $apollo }, + data() { + return { + ...data, + }; + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const findMetricCard = () => wrapper.find(MetricCard); + + describe('while loading', () => { + beforeEach(() => { + createComponent({ loading: true }); + }); + + it('displays the metric card with isLoading=true', () => { + expect(findMetricCard().props('isLoading')).toBe(true); + }); + }); + + describe('with data', () => { + beforeEach(() => { + createComponent({ data: { counts: countsMockData } }); + }); + + it('passes the counts data to the metric card', () => { + expect(findMetricCard().props('metrics')).toEqual(countsMockData); + }); + }); +}); diff --git a/spec/frontend/analytics/instance_statistics/mock_data.js b/spec/frontend/analytics/instance_statistics/mock_data.js new file mode 100644 index 00000000000..9fabf3a4c65 --- /dev/null +++ b/spec/frontend/analytics/instance_statistics/mock_data.js @@ -0,0 +1,4 @@ +export default [ + { key: 'projects', value: 10, label: 'Projects' }, + { key: 'groups', value: 20, label: 'Group' }, +]; diff --git a/spec/frontend/analytics/shared/components/metric_card_spec.js b/spec/frontend/analytics/shared/components/metric_card_spec.js new file mode 100644 index 00000000000..e89d499ed9b --- /dev/null +++ b/spec/frontend/analytics/shared/components/metric_card_spec.js @@ -0,0 +1,129 @@ +import { mount } from '@vue/test-utils'; +import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; +import MetricCard from '~/analytics/shared/components/metric_card.vue'; + +const metrics = [ + { key: 'first_metric', value: 10, label: 'First metric', unit: 'days', link: 'some_link' }, + { key: 'second_metric', value: 20, label: 'Yet another metric' }, + { key: 'third_metric', value: null, label: 'Null metric without value', unit: 'parsecs' }, + { key: 'fourth_metric', value: '-', label: 'Metric without value', unit: 'parsecs' }, +]; + +const defaultProps = { + title: 'My fancy title', + isLoading: false, + metrics, +}; + +describe('MetricCard', () => { + let wrapper; + + const factory = (props = defaultProps) => { + wrapper = mount(MetricCard, { + propsData: { + ...defaultProps, + ...props, + }, + directives: { + GlTooltip: createMockDirective(), + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findTitle = () => wrapper.find({ ref: 'title' }); + const findLoadingIndicator = () => wrapper.find(GlSkeletonLoading); + const findMetricsWrapper = () => wrapper.find({ ref: 'metricsWrapper' }); + const findMetricItem = () => wrapper.findAll({ ref: 'metricItem' }); + const findTooltip = () => wrapper.find('[data-testid="tooltip"]'); + + describe('template', () => { + it('renders the title', () => { + factory(); + + expect(findTitle().text()).toContain('My fancy title'); + }); + + describe('when isLoading is true', () => { + beforeEach(() => { + factory({ isLoading: true }); + }); + + it('displays a loading indicator', () => { + expect(findLoadingIndicator().exists()).toBe(true); + }); + + it('does not display the metrics container', () => { + expect(findMetricsWrapper().exists()).toBe(false); + }); + }); + + describe('when isLoading is false', () => { + beforeEach(() => { + factory({ isLoading: false }); + }); + + it('does not display a loading indicator', () => { + expect(findLoadingIndicator().exists()).toBe(false); + }); + + it('displays the metrics container', () => { + expect(findMetricsWrapper().exists()).toBe(true); + }); + + it('renders two metrics', () => { + expect(findMetricItem()).toHaveLength(metrics.length); + }); + + describe('with tooltip text', () => { + const tooltipText = 'This is a tooltip'; + const tooltipMetric = { + key: 'fifth_metric', + value: '-', + label: 'Metric with tooltip', + unit: 'parsecs', + tooltipText, + }; + + beforeEach(() => { + factory({ + isLoading: false, + metrics: [tooltipMetric], + }); + }); + + it('will render a tooltip', () => { + const tt = getBinding(findTooltip().element, 'gl-tooltip'); + expect(tt.value.title).toEqual(tooltipText); + }); + }); + + describe.each` + columnIndex | label | value | unit | link + ${0} | ${'First metric'} | ${10} | ${' days'} | ${'some_link'} + ${1} | ${'Yet another metric'} | ${20} | ${''} | ${null} + ${2} | ${'Null metric without value'} | ${'-'} | ${''} | ${null} + ${3} | ${'Metric without value'} | ${'-'} | ${''} | ${null} + `('metric columns', ({ columnIndex, label, value, unit, link }) => { + it(`renders ${value}${unit} ${label} with URL ${link}`, () => { + const allMetricItems = findMetricItem(); + const metricItem = allMetricItems.at(columnIndex); + const text = metricItem.text(); + + expect(text).toContain(`${value}${unit}`); + expect(text).toContain(label); + + if (link) { + expect(metricItem.find('a').attributes('href')).toBe(link); + } else { + expect(metricItem.find('a').exists()).toBe(false); + } + }); + }); + }); + }); +}); |