summaryrefslogtreecommitdiff
path: root/spec/frontend
diff options
context:
space:
mode:
authorManoj MJ <mmj@gitlab.com>2019-09-09 03:38:42 +0000
committerAsh McKenzie <amckenzie@gitlab.com>2019-09-09 03:38:42 +0000
commitb041321a355b507cd9329e80935e960c2b9114eb (patch)
tree5013fa7c76955750a869b5a071a1d8d8cecd9686 /spec/frontend
parente3763f9cb60e7f1ddf8c40ddc4bf05747e944f9b (diff)
downloadgitlab-ce-b041321a355b507cd9329e80935e960c2b9114eb.tar.gz
Application Statistics API
This change implements Application Statistics API
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js73
-rw-r--r--spec/frontend/admin/statistics_panel/mock_data.js15
-rw-r--r--spec/frontend/admin/statistics_panel/store/actions_spec.js115
-rw-r--r--spec/frontend/admin/statistics_panel/store/getters_spec.js48
-rw-r--r--spec/frontend/admin/statistics_panel/store/mutations_spec.js41
5 files changed, 292 insertions, 0 deletions
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
new file mode 100644
index 00000000000..25b1d432e2d
--- /dev/null
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -0,0 +1,73 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import StatisticsPanelApp from '~/admin/statistics_panel/components/app.vue';
+import statisticsLabels from '~/admin/statistics_panel/constants';
+import createStore from '~/admin/statistics_panel/store';
+import { GlLoadingIcon } from '@gitlab/ui';
+import mockStatistics from '../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Admin statistics app', () => {
+ let wrapper;
+ let store;
+ let axiosMock;
+
+ const createComponent = () => {
+ wrapper = shallowMount(StatisticsPanelApp, {
+ localVue,
+ store,
+ sync: false,
+ });
+ };
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ axiosMock.onGet(/api\/(.*)\/application\/statistics/).reply(200);
+ store = createStore();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findStats = idx => wrapper.findAll('.js-stats').at(idx);
+
+ describe('template', () => {
+ describe('when app is loading', () => {
+ it('renders a loading indicator', () => {
+ store.dispatch('requestStatistics');
+ createComponent();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('when app has finished loading', () => {
+ const statistics = convertObjectPropsToCamelCase(mockStatistics, { deep: true });
+
+ it.each`
+ statistic | count | index
+ ${'forks'} | ${12} | ${0}
+ ${'issues'} | ${180} | ${1}
+ ${'mergeRequests'} | ${31} | ${2}
+ ${'notes'} | ${986} | ${3}
+ ${'snippets'} | ${50} | ${4}
+ ${'sshKeys'} | ${10} | ${5}
+ ${'milestones'} | ${40} | ${6}
+ ${'activeUsers'} | ${50} | ${7}
+ `('renders the count for the $statistic statistic', ({ statistic, count, index }) => {
+ const label = statisticsLabels[statistic];
+ store.dispatch('receiveStatisticsSuccess', statistics);
+ createComponent();
+
+ expect(findStats(index).text()).toContain(label);
+ expect(findStats(index).text()).toContain(count);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/statistics_panel/mock_data.js b/spec/frontend/admin/statistics_panel/mock_data.js
new file mode 100644
index 00000000000..6d861059dfd
--- /dev/null
+++ b/spec/frontend/admin/statistics_panel/mock_data.js
@@ -0,0 +1,15 @@
+const mockStatistics = {
+ forks: 12,
+ issues: 180,
+ merge_requests: 31,
+ notes: 986,
+ snippets: 50,
+ ssh_keys: 10,
+ milestones: 40,
+ users: 50,
+ projects: 29,
+ groups: 9,
+ active_users: 50,
+};
+
+export default mockStatistics;
diff --git a/spec/frontend/admin/statistics_panel/store/actions_spec.js b/spec/frontend/admin/statistics_panel/store/actions_spec.js
new file mode 100644
index 00000000000..9b18b1aebda
--- /dev/null
+++ b/spec/frontend/admin/statistics_panel/store/actions_spec.js
@@ -0,0 +1,115 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import * as actions from '~/admin/statistics_panel/store/actions';
+import * as types from '~/admin/statistics_panel/store/mutation_types';
+import getInitialState from '~/admin/statistics_panel/store/state';
+import mockStatistics from '../mock_data';
+
+describe('Admin statistics panel actions', () => {
+ let mock;
+ let state;
+
+ beforeEach(() => {
+ state = getInitialState();
+ mock = new MockAdapter(axios);
+ });
+
+ describe('fetchStatistics', () => {
+ describe('success', () => {
+ beforeEach(() => {
+ mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(200, mockStatistics);
+ });
+
+ it('dispatches success with received data', done =>
+ testAction(
+ actions.fetchStatistics,
+ null,
+ state,
+ [],
+ [
+ { type: 'requestStatistics' },
+ {
+ type: 'receiveStatisticsSuccess',
+ payload: expect.objectContaining(
+ convertObjectPropsToCamelCase(mockStatistics, { deep: true }),
+ ),
+ },
+ ],
+ done,
+ ));
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(500);
+ });
+
+ it('dispatches error', done =>
+ testAction(
+ actions.fetchStatistics,
+ null,
+ state,
+ [],
+ [
+ {
+ type: 'requestStatistics',
+ },
+ {
+ type: 'receiveStatisticsError',
+ payload: new Error('Request failed with status code 500'),
+ },
+ ],
+ done,
+ ));
+ });
+ });
+
+ describe('requestStatistic', () => {
+ it('should commit the request mutation', done =>
+ testAction(
+ actions.requestStatistics,
+ null,
+ state,
+ [{ type: types.REQUEST_STATISTICS }],
+ [],
+ done,
+ ));
+ });
+
+ describe('receiveStatisticsSuccess', () => {
+ it('should commit received data', done =>
+ testAction(
+ actions.receiveStatisticsSuccess,
+ mockStatistics,
+ state,
+ [
+ {
+ type: types.RECEIVE_STATISTICS_SUCCESS,
+ payload: mockStatistics,
+ },
+ ],
+ [],
+ done,
+ ));
+ });
+
+ describe('receiveStatisticsError', () => {
+ it('should commit error', done => {
+ testAction(
+ actions.receiveStatisticsError,
+ 500,
+ state,
+ [
+ {
+ type: types.RECEIVE_STATISTICS_ERROR,
+ payload: 500,
+ },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/admin/statistics_panel/store/getters_spec.js b/spec/frontend/admin/statistics_panel/store/getters_spec.js
new file mode 100644
index 00000000000..152d82531ed
--- /dev/null
+++ b/spec/frontend/admin/statistics_panel/store/getters_spec.js
@@ -0,0 +1,48 @@
+import createState from '~/admin/statistics_panel/store/state';
+import * as getters from '~/admin/statistics_panel/store/getters';
+
+describe('Admin statistics panel getters', () => {
+ let state;
+
+ beforeEach(() => {
+ state = createState();
+ });
+
+ describe('getStatistics', () => {
+ describe('when statistics data exists', () => {
+ it('returns an array of statistics objects with key, label and value', () => {
+ state.statistics = { forks: 10, issues: 20 };
+
+ const statisticsLabels = {
+ forks: 'Forks',
+ issues: 'Issues',
+ };
+
+ const statisticsData = [
+ { key: 'forks', label: 'Forks', value: 10 },
+ { key: 'issues', label: 'Issues', value: 20 },
+ ];
+
+ expect(getters.getStatistics(state)(statisticsLabels)).toEqual(statisticsData);
+ });
+ });
+
+ describe('when no statistics data exists', () => {
+ it('returns an array of statistics objects with key, label and sets value to null', () => {
+ state.statistics = null;
+
+ const statisticsLabels = {
+ forks: 'Forks',
+ issues: 'Issues',
+ };
+
+ const statisticsData = [
+ { key: 'forks', label: 'Forks', value: null },
+ { key: 'issues', label: 'Issues', value: null },
+ ];
+
+ expect(getters.getStatistics(state)(statisticsLabels)).toEqual(statisticsData);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/admin/statistics_panel/store/mutations_spec.js b/spec/frontend/admin/statistics_panel/store/mutations_spec.js
new file mode 100644
index 00000000000..179f38d2bc5
--- /dev/null
+++ b/spec/frontend/admin/statistics_panel/store/mutations_spec.js
@@ -0,0 +1,41 @@
+import mutations from '~/admin/statistics_panel/store/mutations';
+import * as types from '~/admin/statistics_panel/store/mutation_types';
+import getInitialState from '~/admin/statistics_panel/store/state';
+import mockStatistics from '../mock_data';
+
+describe('Admin statistics panel mutations', () => {
+ let state;
+
+ beforeEach(() => {
+ state = getInitialState();
+ });
+
+ describe(`${types.REQUEST_STATISTICS}`, () => {
+ it('sets isLoading to true', () => {
+ mutations[types.REQUEST_STATISTICS](state);
+
+ expect(state.isLoading).toBe(true);
+ });
+ });
+
+ describe(`${types.RECEIVE_STATISTICS_SUCCESS}`, () => {
+ it('updates the store with the with statistics', () => {
+ mutations[types.RECEIVE_STATISTICS_SUCCESS](state, mockStatistics);
+
+ expect(state.isLoading).toBe(false);
+ expect(state.error).toBe(null);
+ expect(state.statistics).toEqual(mockStatistics);
+ });
+ });
+
+ describe(`${types.RECEIVE_STATISTICS_ERROR}`, () => {
+ it('sets error and clears data', () => {
+ const error = 500;
+ mutations[types.RECEIVE_STATISTICS_ERROR](state, error);
+
+ expect(state.isLoading).toBe(false);
+ expect(state.error).toBe(error);
+ expect(state.statistics).toEqual(null);
+ });
+ });
+});