summaryrefslogtreecommitdiff
path: root/spec/frontend/analytics/instance_statistics/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/analytics/instance_statistics/components')
-rw-r--r--spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap41
-rw-r--r--spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap161
-rw-r--r--spec/frontend/analytics/instance_statistics/components/app_spec.js17
-rw-r--r--spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js177
-rw-r--r--spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js189
-rw-r--r--spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js216
-rw-r--r--spec/frontend/analytics/instance_statistics/components/users_chart_spec.js45
7 files changed, 458 insertions, 388 deletions
diff --git a/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap b/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap
new file mode 100644
index 00000000000..29bcd5f223b
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/__snapshots__/instance_statistics_count_chart_spec.js.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`InstanceStatisticsCountChart when fetching more data when the fetchMore query returns data passes the data to the line chart 1`] = `
+Array [
+ Object {
+ "data": Array [
+ Array [
+ "2020-07-01",
+ 41,
+ ],
+ Array [
+ "2020-06-01",
+ 22,
+ ],
+ Array [
+ "2020-08-01",
+ 5,
+ ],
+ ],
+ "name": "Mock Query",
+ },
+]
+`;
+
+exports[`InstanceStatisticsCountChart with data passes the data to the line chart 1`] = `
+Array [
+ Object {
+ "data": Array [
+ Array [
+ "2020-07-01",
+ 41,
+ ],
+ Array [
+ "2020-06-01",
+ 22,
+ ],
+ ],
+ "name": "Mock Query",
+ },
+]
+`;
diff --git a/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap b/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap
deleted file mode 100644
index 0b3b685a9f2..00000000000
--- a/spec/frontend/analytics/instance_statistics/components/__snapshots__/pipelines_chart_spec.js.snap
+++ /dev/null
@@ -1,161 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PipelinesChart when fetching more data when the fetchMore query returns data passes the data to the line chart 1`] = `
-Array [
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Total",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Succeeded",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Failed",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Canceled",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- Array [
- "2020-08-01",
- 5,
- ],
- ],
- "name": "Skipped",
- },
-]
-`;
-
-exports[`PipelinesChart with data passes the data to the line chart 1`] = `
-Array [
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Total",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- ],
- "name": "Succeeded",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 21,
- ],
- Array [
- "2020-07-01",
- 10,
- ],
- ],
- "name": "Failed",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Canceled",
- },
- Object {
- "data": Array [
- Array [
- "2020-06-01",
- 22,
- ],
- Array [
- "2020-07-01",
- 41,
- ],
- ],
- "name": "Skipped",
- },
-]
-`;
diff --git a/spec/frontend/analytics/instance_statistics/components/app_spec.js b/spec/frontend/analytics/instance_statistics/components/app_spec.js
index df13c9f82a9..8ac663b3046 100644
--- a/spec/frontend/analytics/instance_statistics/components/app_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js
@@ -1,8 +1,9 @@
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';
-import PipelinesChart from '~/analytics/instance_statistics/components/pipelines_chart.vue';
+import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
+import ProjectsAndGroupsChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
describe('InstanceStatisticsApp', () => {
let wrapper;
@@ -24,11 +25,21 @@ describe('InstanceStatisticsApp', () => {
expect(wrapper.find(InstanceCounts).exists()).toBe(true);
});
- it('displays the pipelines chart component', () => {
- expect(wrapper.find(PipelinesChart).exists()).toBe(true);
+ ['Pipelines', 'Issues & Merge Requests'].forEach(instance => {
+ it(`displays the ${instance} chart`, () => {
+ const chartTitles = wrapper
+ .findAll(InstanceStatisticsCountChart)
+ .wrappers.map(chartComponent => chartComponent.props('chartTitle'));
+
+ expect(chartTitles).toContain(instance);
+ });
});
it('displays the users chart component', () => {
expect(wrapper.find(UsersChart).exists()).toBe(true);
});
+
+ it('displays the projects and groups chart component', () => {
+ expect(wrapper.find(ProjectsAndGroupsChart).exists()).toBe(true);
+ });
});
diff --git a/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
new file mode 100644
index 00000000000..275a84988f8
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/instance_statistics_count_chart_spec.js
@@ -0,0 +1,177 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { GlAlert } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import InstanceStatisticsCountChart from '~/analytics/instance_statistics/components/instance_statistics_count_chart.vue';
+import statsQuery from '~/analytics/instance_statistics/graphql/queries/instance_count.query.graphql';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import { mockCountsData1 } from '../mock_data';
+import { mockQueryResponse, mockApolloResponse } from '../apollo_mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+const loadChartErrorMessage = 'My load error message';
+const noDataMessage = 'My no data message';
+
+const queryResponseDataKey = 'instanceStatisticsMeasurements';
+const identifier = 'MOCK_QUERY';
+const mockQueryConfig = {
+ identifier,
+ title: 'Mock Query',
+ query: statsQuery,
+ loadError: 'Failed to load mock query data',
+};
+
+const mockChartConfig = {
+ loadChartErrorMessage,
+ noDataMessage,
+ chartTitle: 'Foo',
+ yAxisTitle: 'Bar',
+ xAxisTitle: 'Baz',
+ queries: [mockQueryConfig],
+};
+
+describe('InstanceStatisticsCountChart', () => {
+ let wrapper;
+ let queryHandler;
+
+ const createComponent = ({ responseHandler }) => {
+ return shallowMount(InstanceStatisticsCountChart, {
+ localVue,
+ apolloProvider: createMockApollo([[statsQuery, responseHandler]]),
+ propsData: { ...mockChartConfig },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findLoader = () => wrapper.find(ChartSkeletonLoader);
+ const findChart = () => wrapper.find(GlLineChart);
+ const findAlert = () => wrapper.find(GlAlert);
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, loading: true });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('requests data', () => {
+ expect(queryHandler).toBeCalledTimes(1);
+ });
+
+ it('displays the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+
+ it('does not show an error', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('without data', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: [] });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('renders an no data message', () => {
+ expect(findAlert().text()).toBe(noDataMessage);
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('with data', () => {
+ beforeEach(() => {
+ queryHandler = mockQueryResponse({ key: queryResponseDataKey, data: mockCountsData1 });
+ wrapper = createComponent({ responseHandler: queryHandler });
+ });
+
+ it('requests data', () => {
+ expect(queryHandler).toBeCalledTimes(1);
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toMatchSnapshot();
+ });
+
+ it('does not show an error', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('when fetching more data', () => {
+ const recordedAt = '2020-08-01';
+ describe('when the fetchMore query returns data', () => {
+ beforeEach(async () => {
+ const newData = [{ recordedAt, count: 5 }];
+ queryHandler = mockQueryResponse({
+ key: queryResponseDataKey,
+ data: mockCountsData1,
+ additionalData: newData,
+ });
+
+ wrapper = createComponent({ responseHandler: queryHandler });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('requests data twice', () => {
+ expect(queryHandler).toBeCalledTimes(2);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toMatchSnapshot();
+ });
+ });
+
+ describe('when the fetchMore query throws an error', () => {
+ beforeEach(async () => {
+ queryHandler = jest.fn().mockResolvedValueOnce(
+ mockApolloResponse({
+ key: queryResponseDataKey,
+ data: mockCountsData1,
+ hasNextPage: true,
+ }),
+ );
+
+ wrapper = createComponent({ responseHandler: queryHandler });
+ jest
+ .spyOn(wrapper.vm.$apollo.queries[identifier], 'fetchMore')
+ .mockImplementation(jest.fn().mockRejectedValue());
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[identifier].fetchMore).toHaveBeenCalledTimes(1);
+ });
+
+ it('show an error message', () => {
+ expect(findAlert().text()).toBe(loadChartErrorMessage);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js
deleted file mode 100644
index a06d66f783e..00000000000
--- a/spec/frontend/analytics/instance_statistics/components/pipelines_chart_spec.js
+++ /dev/null
@@ -1,189 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLineChart } from '@gitlab/ui/dist/charts';
-import { GlAlert } from '@gitlab/ui';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'jest/helpers/mock_apollo_helper';
-import PipelinesChart from '~/analytics/instance_statistics/components/pipelines_chart.vue';
-import pipelinesStatsQuery from '~/analytics/instance_statistics/graphql/queries/pipeline_stats.query.graphql';
-import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
-import { mockCountsData1, mockCountsData2 } from '../mock_data';
-import { getApolloResponse } from '../apollo_mock_data';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('PipelinesChart', () => {
- let wrapper;
- let queryHandler;
-
- const createApolloProvider = pipelineStatsHandler => {
- return createMockApollo([[pipelinesStatsQuery, pipelineStatsHandler]]);
- };
-
- const createComponent = apolloProvider => {
- return shallowMount(PipelinesChart, {
- localVue,
- apolloProvider,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findLoader = () => wrapper.find(ChartSkeletonLoader);
- const findChart = () => wrapper.find(GlLineChart);
- const findAlert = () => wrapper.find(GlAlert);
-
- describe('while loading', () => {
- beforeEach(() => {
- queryHandler = jest.fn().mockReturnValue(new Promise(() => {}));
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('requests data', () => {
- expect(queryHandler).toBeCalledTimes(1);
- });
-
- it('displays the skeleton loader', () => {
- expect(findLoader().exists()).toBe(true);
- });
-
- it('hides the chart', () => {
- expect(findChart().exists()).toBe(false);
- });
-
- it('does not show an error', () => {
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('without data', () => {
- beforeEach(() => {
- const emptyResponse = getApolloResponse();
- queryHandler = jest.fn().mockResolvedValue(emptyResponse);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('renders an no data message', () => {
- expect(findAlert().text()).toBe('There is no data available.');
- });
-
- it('hides the skeleton loader', () => {
- expect(findLoader().exists()).toBe(false);
- });
-
- it('renders the chart', () => {
- expect(findChart().exists()).toBe(false);
- });
- });
-
- describe('with data', () => {
- beforeEach(() => {
- const response = getApolloResponse({
- pipelinesTotal: mockCountsData1,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData2,
- pipelinesCanceled: mockCountsData1,
- pipelinesSkipped: mockCountsData1,
- });
- queryHandler = jest.fn().mockResolvedValue(response);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- });
-
- it('requests data', () => {
- expect(queryHandler).toBeCalledTimes(1);
- });
-
- it('hides the skeleton loader', () => {
- expect(findLoader().exists()).toBe(false);
- });
-
- it('renders the chart', () => {
- expect(findChart().exists()).toBe(true);
- });
-
- it('passes the data to the line chart', () => {
- expect(findChart().props('data')).toMatchSnapshot();
- });
-
- it('does not show an error', () => {
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('when fetching more data', () => {
- const recordedAt = '2020-08-01';
- describe('when the fetchMore query returns data', () => {
- beforeEach(async () => {
- const newData = { recordedAt, count: 5 };
- const firstResponse = getApolloResponse({
- pipelinesTotal: mockCountsData2,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData1,
- pipelinesCanceled: mockCountsData2,
- pipelinesSkipped: mockCountsData2,
- hasNextPage: true,
- });
- const secondResponse = getApolloResponse({
- pipelinesTotal: [newData],
- pipelinesSucceeded: [newData],
- pipelinesFailed: [newData],
- pipelinesCanceled: [newData],
- pipelinesSkipped: [newData],
- hasNextPage: false,
- });
- queryHandler = jest
- .fn()
- .mockResolvedValueOnce(firstResponse)
- .mockResolvedValueOnce(secondResponse);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
-
- await wrapper.vm.$nextTick();
- });
-
- it('requests data twice', () => {
- expect(queryHandler).toBeCalledTimes(2);
- });
-
- it('passes the data to the line chart', () => {
- expect(findChart().props('data')).toMatchSnapshot();
- });
- });
-
- describe('when the fetchMore query throws an error', () => {
- beforeEach(async () => {
- const response = getApolloResponse({
- pipelinesTotal: mockCountsData2,
- pipelinesSucceeded: mockCountsData2,
- pipelinesFailed: mockCountsData1,
- pipelinesCanceled: mockCountsData2,
- pipelinesSkipped: mockCountsData2,
- hasNextPage: true,
- });
- queryHandler = jest.fn().mockResolvedValue(response);
- const apolloProvider = createApolloProvider(queryHandler);
- wrapper = createComponent(apolloProvider);
- jest
- .spyOn(wrapper.vm.$apollo.queries.pipelineStats, 'fetchMore')
- .mockImplementation(jest.fn().mockRejectedValue());
- await wrapper.vm.$nextTick();
- });
-
- it('calls fetchMore', () => {
- expect(wrapper.vm.$apollo.queries.pipelineStats.fetchMore).toHaveBeenCalledTimes(1);
- });
-
- it('show an error message', () => {
- expect(findAlert().text()).toBe(
- 'Could not load the pipelines chart. Please refresh the page to try again.',
- );
- });
- });
- });
-});
diff --git a/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
new file mode 100644
index 00000000000..d9f42430aa8
--- /dev/null
+++ b/spec/frontend/analytics/instance_statistics/components/projects_and_groups_chart_spec.js
@@ -0,0 +1,216 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlLineChart } from '@gitlab/ui/dist/charts';
+import { GlAlert } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+import { useFakeDate } from 'helpers/fake_date';
+import ProjectsAndGroupChart from '~/analytics/instance_statistics/components/projects_and_groups_chart.vue';
+import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
+import projectsQuery from '~/analytics/instance_statistics/graphql/queries/projects.query.graphql';
+import groupsQuery from '~/analytics/instance_statistics/graphql/queries/groups.query.graphql';
+import { mockCountsData2, roundedSortedCountsMonthlyChartData2 } from '../mock_data';
+import { mockQueryResponse } from '../apollo_mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('ProjectsAndGroupChart', () => {
+ let wrapper;
+ let queryResponses = { projects: null, groups: null };
+ const mockAdditionalData = [{ recordedAt: '2020-07-21', count: 5 }];
+
+ const createComponent = ({
+ loadingError = false,
+ projects = [],
+ groups = [],
+ projectsLoading = false,
+ groupsLoading = false,
+ projectsAdditionalData = [],
+ groupsAdditionalData = [],
+ } = {}) => {
+ queryResponses = {
+ projects: mockQueryResponse({
+ key: 'projects',
+ data: projects,
+ loading: projectsLoading,
+ additionalData: projectsAdditionalData,
+ }),
+ groups: mockQueryResponse({
+ key: 'groups',
+ data: groups,
+ loading: groupsLoading,
+ additionalData: groupsAdditionalData,
+ }),
+ };
+
+ return shallowMount(ProjectsAndGroupChart, {
+ props: {
+ startDate: useFakeDate(2020, 9, 26),
+ endDate: useFakeDate(2020, 10, 1),
+ totalDataPoints: mockCountsData2.length,
+ },
+ localVue,
+ apolloProvider: createMockApollo([
+ [projectsQuery, queryResponses.projects],
+ [groupsQuery, queryResponses.groups],
+ ]),
+ data() {
+ return { loadingError };
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ queryResponses = {
+ projects: null,
+ groups: null,
+ };
+ });
+
+ const findLoader = () => wrapper.find(ChartSkeletonLoader);
+ const findAlert = () => wrapper.find(GlAlert);
+ const findChart = () => wrapper.find(GlLineChart);
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ projectsLoading: true, groupsLoading: true });
+ });
+
+ it('displays the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('while loading 1 data set', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ projects: mockCountsData2,
+ groupsLoading: true,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+ });
+
+ describe('without data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ projects: [] });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders a no data message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('does not render the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe('with data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ projects: mockCountsData2 });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('renders the chart', () => {
+ expect(findChart().exists()).toBe(true);
+ });
+
+ it('passes the data to the line chart', () => {
+ expect(findChart().props('data')).toEqual([
+ { data: roundedSortedCountsMonthlyChartData2, name: 'Total projects' },
+ { data: [], name: 'Total groups' },
+ ]);
+ });
+ });
+
+ describe('with errors', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ loadingError: true });
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders an error message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+
+ it('hides the skeleton loader', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+
+ it('hides the chart', () => {
+ expect(findChart().exists()).toBe(false);
+ });
+ });
+
+ describe.each`
+ metric | loadingState | newData
+ ${'projects'} | ${{ projectsAdditionalData: mockAdditionalData }} | ${{ projects: mockCountsData2 }}
+ ${'groups'} | ${{ groupsAdditionalData: mockAdditionalData }} | ${{ groups: mockCountsData2 }}
+ `('$metric - fetchMore', ({ metric, loadingState, newData }) => {
+ describe('when the fetchMore query returns data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ ...loadingState,
+ ...newData,
+ });
+
+ jest.spyOn(wrapper.vm.$apollo.queries[metric], 'fetchMore');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('requests data twice', () => {
+ expect(queryResponses[metric]).toBeCalledTimes(2);
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[metric].fetchMore).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when the fetchMore query throws an error', () => {
+ beforeEach(() => {
+ wrapper = createComponent({
+ ...loadingState,
+ ...newData,
+ });
+
+ jest
+ .spyOn(wrapper.vm.$apollo.queries[metric], 'fetchMore')
+ .mockImplementation(jest.fn().mockRejectedValue());
+ return wrapper.vm.$nextTick();
+ });
+
+ it('calls fetchMore', () => {
+ expect(wrapper.vm.$apollo.queries[metric].fetchMore).toHaveBeenCalledTimes(1);
+ });
+
+ it('renders an error message', () => {
+ expect(findAlert().text()).toBe('No data available.');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
index 7509c1e6626..6ed9d203f3d 100644
--- a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
+++ b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js
@@ -7,7 +7,12 @@ import { useFakeDate } from 'helpers/fake_date';
import UsersChart from '~/analytics/instance_statistics/components/users_chart.vue';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import usersQuery from '~/analytics/instance_statistics/graphql/queries/users.query.graphql';
-import { mockCountsData2, roundedSortedCountsMonthlyChartData2, mockPageInfo } from '../mock_data';
+import {
+ mockCountsData1,
+ mockCountsData2,
+ roundedSortedCountsMonthlyChartData2,
+} from '../mock_data';
+import { mockQueryResponse } from '../apollo_mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
@@ -16,43 +21,13 @@ describe('UsersChart', () => {
let wrapper;
let queryHandler;
- const mockApolloResponse = ({ loading = false, hasNextPage = false, users }) => ({
- data: {
- users: {
- pageInfo: { ...mockPageInfo, hasNextPage },
- nodes: users,
- loading,
- },
- },
- });
-
- const mockQueryResponse = ({ users, loading = false, hasNextPage = false }) => {
- const apolloQueryResponse = mockApolloResponse({ loading, hasNextPage, users });
- if (loading) {
- return jest.fn().mockReturnValue(new Promise(() => {}));
- }
- if (hasNextPage) {
- return jest
- .fn()
- .mockResolvedValueOnce(apolloQueryResponse)
- .mockResolvedValueOnce(
- mockApolloResponse({
- loading,
- hasNextPage: false,
- users: [{ recordedAt: '2020-07-21', count: 5 }],
- }),
- );
- }
- return jest.fn().mockResolvedValue(apolloQueryResponse);
- };
-
const createComponent = ({
loadingError = false,
loading = false,
users = [],
- hasNextPage = false,
+ additionalData = [],
} = {}) => {
- queryHandler = mockQueryResponse({ users, loading, hasNextPage });
+ queryHandler = mockQueryResponse({ key: 'users', data: users, loading, additionalData });
return shallowMount(UsersChart, {
props: {
@@ -157,7 +132,7 @@ describe('UsersChart', () => {
beforeEach(async () => {
wrapper = createComponent({
users: mockCountsData2,
- hasNextPage: true,
+ additionalData: mockCountsData1,
});
jest.spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore');
@@ -177,7 +152,7 @@ describe('UsersChart', () => {
beforeEach(() => {
wrapper = createComponent({
users: mockCountsData2,
- hasNextPage: true,
+ additionalData: mockCountsData1,
});
jest