diff options
Diffstat (limited to 'spec/frontend/analytics')
3 files changed, 217 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 index 39f6d1b450a..df13c9f82a9 100644 --- a/spec/frontend/analytics/instance_statistics/components/app_spec.js +++ b/spec/frontend/analytics/instance_statistics/components/app_spec.js @@ -2,6 +2,7 @@ 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 UsersChart from '~/analytics/instance_statistics/components/users_chart.vue'; describe('InstanceStatisticsApp', () => { let wrapper; @@ -26,4 +27,8 @@ describe('InstanceStatisticsApp', () => { it('displays the pipelines chart component', () => { expect(wrapper.find(PipelinesChart).exists()).toBe(true); }); + + it('displays the users chart component', () => { + expect(wrapper.find(UsersChart).exists()).toBe(true); + }); }); diff --git a/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js new file mode 100644 index 00000000000..7509c1e6626 --- /dev/null +++ b/spec/frontend/analytics/instance_statistics/components/users_chart_spec.js @@ -0,0 +1,200 @@ +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { GlAreaChart } 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 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'; + +const localVue = createLocalVue(); +localVue.use(VueApollo); + +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, + } = {}) => { + queryHandler = mockQueryResponse({ users, loading, hasNextPage }); + + return shallowMount(UsersChart, { + props: { + startDate: useFakeDate(2020, 9, 26), + endDate: useFakeDate(2020, 10, 1), + totalDataPoints: mockCountsData2.length, + }, + localVue, + apolloProvider: createMockApollo([[usersQuery, queryHandler]]), + data() { + return { loadingError }; + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const findLoader = () => wrapper.find(ChartSkeletonLoader); + const findAlert = () => wrapper.find(GlAlert); + const findChart = () => wrapper.find(GlAreaChart); + + describe('while loading', () => { + beforeEach(() => { + wrapper = createComponent({ loading: true }); + }); + + it('displays the skeleton loader', () => { + expect(findLoader().exists()).toBe(true); + }); + + it('hides the chart', () => { + expect(findChart().exists()).toBe(false); + }); + }); + + describe('without data', () => { + beforeEach(async () => { + wrapper = createComponent({ users: [] }); + await wrapper.vm.$nextTick(); + }); + + 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(async () => { + wrapper = createComponent({ users: 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 users' }, + ]); + }); + }); + + describe('with errors', () => { + beforeEach(async () => { + wrapper = createComponent({ loadingError: true }); + await wrapper.vm.$nextTick(); + }); + + it('renders an error message', () => { + expect(findAlert().text()).toBe( + 'Could not load the user chart. Please refresh the page to try again.', + ); + }); + + it('hides the skeleton loader', () => { + expect(findLoader().exists()).toBe(false); + }); + + it('renders the chart', () => { + expect(findChart().exists()).toBe(false); + }); + }); + + describe('when fetching more data', () => { + describe('when the fetchMore query returns data', () => { + beforeEach(async () => { + wrapper = createComponent({ + users: mockCountsData2, + hasNextPage: true, + }); + + jest.spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore'); + await wrapper.vm.$nextTick(); + }); + + it('requests data twice', () => { + expect(queryHandler).toBeCalledTimes(2); + }); + + it('calls fetchMore', () => { + expect(wrapper.vm.$apollo.queries.users.fetchMore).toHaveBeenCalledTimes(1); + }); + }); + + describe('when the fetchMore query throws an error', () => { + beforeEach(() => { + wrapper = createComponent({ + users: mockCountsData2, + hasNextPage: true, + }); + + jest + .spyOn(wrapper.vm.$apollo.queries.users, 'fetchMore') + .mockImplementation(jest.fn().mockRejectedValue()); + return wrapper.vm.$nextTick(); + }); + + it('calls fetchMore', () => { + expect(wrapper.vm.$apollo.queries.users.fetchMore).toHaveBeenCalledTimes(1); + }); + + it('renders an error message', () => { + expect(findAlert().text()).toBe( + 'Could not load the user chart. Please refresh the page to try again.', + ); + }); + }); + }); +}); diff --git a/spec/frontend/analytics/instance_statistics/mock_data.js b/spec/frontend/analytics/instance_statistics/mock_data.js index c3f5069da28..b737db4c55f 100644 --- a/spec/frontend/analytics/instance_statistics/mock_data.js +++ b/spec/frontend/analytics/instance_statistics/mock_data.js @@ -28,3 +28,15 @@ export const countsMonthlyChartData2 = [ ['2020-07-01', 9.5], // average of 2020-07-x items ['2020-06-01', 20.666666666666668], // average of 2020-06-x items ]; + +export const roundedSortedCountsMonthlyChartData2 = [ + ['2020-06-01', 21], // average of 2020-06-x items + ['2020-07-01', 10], // average of 2020-07-x items +]; + +export const mockPageInfo = { + hasNextPage: false, + hasPreviousPage: false, + startCursor: null, + endCursor: null, +}; |