Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/analytics/shared/components')
-rw-r--r--spec/frontend/analytics/shared/components/daterange_spec.js41
-rw-r--r--spec/frontend/analytics/shared/components/metric_popover_spec.js102
-rw-r--r--spec/frontend/analytics/shared/components/metric_tile_spec.js81
-rw-r--r--spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js31
4 files changed, 215 insertions, 40 deletions
diff --git a/spec/frontend/analytics/shared/components/daterange_spec.js b/spec/frontend/analytics/shared/components/daterange_spec.js
index 854582abb82..a38df274243 100644
--- a/spec/frontend/analytics/shared/components/daterange_spec.js
+++ b/spec/frontend/analytics/shared/components/daterange_spec.js
@@ -1,7 +1,6 @@
-import { GlDaterangePicker } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { GlDaterangePicker, GlSprintf } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import Daterange from '~/analytics/shared/components/daterange.vue';
const defaultProps = {
@@ -14,13 +13,13 @@ describe('Daterange component', () => {
let wrapper;
- const factory = (props = defaultProps) => {
- wrapper = mount(Daterange, {
+ const factory = (props = defaultProps, mountFn = shallowMount) => {
+ wrapper = mountFn(Daterange, {
propsData: {
...defaultProps,
...props,
},
- directives: { GlTooltip: createMockDirective() },
+ stubs: { GlSprintf },
});
};
@@ -28,9 +27,8 @@ describe('Daterange component', () => {
wrapper.destroy();
});
- const findDaterangePicker = () => wrapper.find(GlDaterangePicker);
-
- const findDateRangeIndicator = () => wrapper.find('.daterange-indicator');
+ const findDaterangePicker = () => wrapper.findComponent(GlDaterangePicker);
+ const findDateRangeIndicator = () => wrapper.findComponent(GlSprintf);
describe('template', () => {
describe('when show is false', () => {
@@ -43,26 +41,24 @@ describe('Daterange component', () => {
describe('when show is true', () => {
it('renders the daterange picker', () => {
factory({ show: true });
+
expect(findDaterangePicker().exists()).toBe(true);
});
});
describe('with a minDate being set', () => {
- it('emits the change event with the minDate when the user enters a start date before the minDate', () => {
+ it('emits the change event with the minDate when the user enters a start date before the minDate', async () => {
const startDate = new Date('2019-09-01');
const endDate = new Date('2019-09-30');
const minDate = new Date('2019-06-01');
- factory({ show: true, startDate, endDate, minDate });
-
+ factory({ show: true, startDate, endDate, minDate }, mount);
const input = findDaterangePicker().find('input');
input.setValue('2019-01-01');
- input.trigger('change');
+ await input.trigger('change');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().change).toEqual([[{ startDate: minDate, endDate }]]);
- });
+ expect(wrapper.emitted().change).toEqual([[{ startDate: minDate, endDate }]]);
});
});
@@ -76,16 +72,13 @@ describe('Daterange component', () => {
});
it('displays the correct number of selected days in the indicator', () => {
- expect(findDateRangeIndicator().find('span').text()).toBe('10 days selected');
+ expect(findDateRangeIndicator().text()).toMatchInterpolatedText('10 days selected');
});
- it('displays a tooltip', () => {
- const icon = wrapper.find('[data-testid="helper-icon"]');
- const tooltip = getBinding(icon.element, 'gl-tooltip');
-
- expect(tooltip).toBeDefined();
- expect(icon.attributes('title')).toBe(
- 'Showing data for workflow items created in this date range. Date range cannot exceed 30 days.',
+ it('sets the tooltip', () => {
+ const tooltip = findDaterangePicker().props('tooltip');
+ expect(tooltip).toBe(
+ 'Showing data for workflow items created in this date range. Date range limited to 30 days.',
);
});
});
diff --git a/spec/frontend/analytics/shared/components/metric_popover_spec.js b/spec/frontend/analytics/shared/components/metric_popover_spec.js
new file mode 100644
index 00000000000..b799c911488
--- /dev/null
+++ b/spec/frontend/analytics/shared/components/metric_popover_spec.js
@@ -0,0 +1,102 @@
+import { GlLink, GlIcon } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
+
+const MOCK_METRIC = {
+ key: 'deployment-frequency',
+ label: 'Deployment Frequency',
+ value: '10.0',
+ unit: 'per day',
+ description: 'Average number of deployments to production per day.',
+ links: [],
+};
+
+describe('MetricPopover', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMountExtended(MetricPopover, {
+ propsData: {
+ target: 'deployment-frequency',
+ ...props,
+ },
+ stubs: {
+ 'gl-popover': { template: '<div><slot name="title"></slot><slot></slot></div>' },
+ },
+ });
+ };
+
+ const findMetricLabel = () => wrapper.findByTestId('metric-label');
+ const findAllMetricLinks = () => wrapper.findAll('[data-testid="metric-link"]');
+ const findMetricDescription = () => wrapper.findByTestId('metric-description');
+ const findMetricDocsLink = () => wrapper.findByTestId('metric-docs-link');
+ const findMetricDocsLinkIcon = () => findMetricDocsLink().find(GlIcon);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the metric label', () => {
+ wrapper = createComponent({ metric: MOCK_METRIC });
+ expect(findMetricLabel().text()).toBe(MOCK_METRIC.label);
+ });
+
+ it('renders the metric description', () => {
+ wrapper = createComponent({ metric: MOCK_METRIC });
+ expect(findMetricDescription().text()).toBe(MOCK_METRIC.description);
+ });
+
+ describe('with links', () => {
+ const links = [
+ {
+ name: 'Deployment frequency',
+ url: '/groups/gitlab-org/-/analytics/ci_cd?tab=deployment-frequency',
+ label: 'Dashboard',
+ },
+ {
+ name: 'Another link',
+ url: '/groups/gitlab-org/-/analytics/another-link',
+ label: 'Another link',
+ },
+ ];
+ const docsLink = {
+ name: 'Deployment frequency',
+ url: '/help/user/analytics/index#definitions',
+ label: 'Go to docs',
+ docs_link: true,
+ };
+ const linksWithDocs = [...links, docsLink];
+
+ describe.each`
+ hasDocsLink | allLinks | displayedMetricLinks
+ ${true} | ${linksWithDocs} | ${links}
+ ${false} | ${links} | ${links}
+ `(
+ 'when one link has docs_link=$hasDocsLink',
+ ({ hasDocsLink, allLinks, displayedMetricLinks }) => {
+ beforeEach(() => {
+ wrapper = createComponent({ metric: { ...MOCK_METRIC, links: allLinks } });
+ });
+
+ displayedMetricLinks.forEach((link, idx) => {
+ it(`renders a link for "${link.name}"`, () => {
+ const allLinkContainers = findAllMetricLinks();
+
+ expect(allLinkContainers.at(idx).text()).toContain(link.name);
+ expect(allLinkContainers.at(idx).find(GlLink).attributes('href')).toBe(link.url);
+ });
+ });
+
+ it(`${hasDocsLink ? 'renders' : "doesn't render"} a docs link`, () => {
+ expect(findMetricDocsLink().exists()).toBe(hasDocsLink);
+
+ if (hasDocsLink) {
+ expect(findMetricDocsLink().attributes('href')).toBe(docsLink.url);
+ expect(findMetricDocsLink().text()).toBe(docsLink.label);
+ expect(findMetricDocsLinkIcon().attributes('name')).toBe('external-link');
+ }
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/analytics/shared/components/metric_tile_spec.js b/spec/frontend/analytics/shared/components/metric_tile_spec.js
new file mode 100644
index 00000000000..980dfad9eb0
--- /dev/null
+++ b/spec/frontend/analytics/shared/components/metric_tile_spec.js
@@ -0,0 +1,81 @@
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
+import MetricTile from '~/analytics/shared/components/metric_tile.vue';
+import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
+import { redirectTo } from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility');
+
+describe('MetricTile', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ return shallowMount(MetricTile, {
+ propsData: {
+ metric: {},
+ ...props,
+ },
+ });
+ };
+
+ const findSingleStat = () => wrapper.findComponent(GlSingleStat);
+ const findPopover = () => wrapper.findComponent(MetricPopover);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ describe('links', () => {
+ it('when the metric has links, it redirects the user on click', () => {
+ const metric = {
+ identifier: 'deploys',
+ value: '10',
+ label: 'Deploys',
+ links: [{ url: 'foo/bar' }],
+ };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ singleStat.vm.$emit('click');
+ expect(redirectTo).toHaveBeenCalledWith('foo/bar');
+ });
+
+ it("when the metric doesn't have links, it won't the user on click", () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ singleStat.vm.$emit('click');
+ expect(redirectTo).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('decimal places', () => {
+ it(`will render 0 decimal places for an integer value`, () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ expect(singleStat.props('animationDecimalPlaces')).toBe(0);
+ });
+
+ it(`will render 1 decimal place for a float value`, () => {
+ const metric = { identifier: 'deploys', value: '10.5', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const singleStat = findSingleStat();
+ expect(singleStat.props('animationDecimalPlaces')).toBe(1);
+ });
+ });
+
+ it('renders a metric popover', () => {
+ const metric = { identifier: 'deploys', value: '10', label: 'Deploys' };
+ wrapper = createComponent({ metric });
+
+ const popover = findPopover();
+ expect(popover.exists()).toBe(true);
+ expect(popover.props()).toMatchObject({ metric, target: metric.identifier });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
index 28d7ebe28df..386fb4eb616 100644
--- a/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
+++ b/spec/frontend/analytics/shared/components/projects_dropdown_filter_spec.js
@@ -1,4 +1,5 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import { TEST_HOST } from 'helpers/test_constants';
@@ -99,9 +100,9 @@ describe('ProjectsDropdownFilter component', () => {
const findDropdownFullPathAtIndex = (index) =>
findDropdownAtIndex(index).find('[data-testid="project-full-path"]');
- const selectDropdownItemAtIndex = (index) => {
+ const selectDropdownItemAtIndex = async (index) => {
findDropdownAtIndex(index).find('button').trigger('click');
- return wrapper.vm.$nextTick();
+ await nextTick();
};
// NOTE: Selected items are now visually separated from unselected items
@@ -132,16 +133,15 @@ describe('ProjectsDropdownFilter component', () => {
expect(spyQuery).toHaveBeenCalledTimes(1);
- await wrapper.vm.$nextTick(() => {
- expect(spyQuery).toHaveBeenCalledWith({
- query: getProjects,
- variables: {
- search: 'gitlab',
- groupFullPath: wrapper.vm.groupNamespace,
- first: 50,
- includeSubgroups: true,
- },
- });
+ await nextTick();
+ expect(spyQuery).toHaveBeenCalledWith({
+ query: getProjects,
+ variables: {
+ search: 'gitlab',
+ groupFullPath: wrapper.vm.groupNamespace,
+ first: 50,
+ includeSubgroups: true,
+ },
});
});
});
@@ -193,7 +193,7 @@ describe('ProjectsDropdownFilter component', () => {
expect(wrapper.text()).toContain('2 projects selected');
findClearAllButton().trigger('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.text()).not.toContain('2 projects selected');
expect(wrapper.text()).toContain('Select projects');
@@ -366,9 +366,8 @@ describe('ProjectsDropdownFilter component', () => {
selectDropdownItemAtIndex(0);
selectDropdownItemAtIndex(1);
- await wrapper.vm.$nextTick().then(() => {
- expect(findDropdownButton().text()).toBe('2 projects selected');
- });
+ await nextTick();
+ expect(findDropdownButton().text()).toBe('2 projects selected');
});
});
});