diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-26 21:06:38 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-26 21:06:38 +0000 |
commit | 59a349817c0869e8e0d750884b34256ca4faefca (patch) | |
tree | abb8297dd313e550184f1933a9dc7795a3749c0a /spec/frontend/monitoring | |
parent | 581c10e344d85729e77fce78513819d159289dc5 (diff) | |
download | gitlab-ce-59a349817c0869e8e0d750884b34256ca4faefca.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/monitoring')
-rw-r--r-- | spec/frontend/monitoring/store/actions_spec.js | 199 |
1 files changed, 113 insertions, 86 deletions
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js index 467e0445a90..83dac6552a2 100644 --- a/spec/frontend/monitoring/store/actions_spec.js +++ b/spec/frontend/monitoring/store/actions_spec.js @@ -1,15 +1,14 @@ import MockAdapter from 'axios-mock-adapter'; import Tracking from '~/tracking'; -import { TEST_HOST } from 'helpers/test_constants'; import testAction from 'helpers/vuex_action_helper'; import axios from '~/lib/utils/axios_utils'; import statusCodes from '~/lib/utils/http_status'; import { backOff } from '~/lib/utils/common_utils'; +import createFlash from '~/flash'; import store from '~/monitoring/stores'; import * as types from '~/monitoring/stores/mutation_types'; import { - backOffRequest, fetchDashboard, receiveMetricsDashboardSuccess, receiveMetricsDashboardFailure, @@ -17,7 +16,6 @@ import { fetchEnvironmentsData, fetchPrometheusMetrics, fetchPrometheusMetric, - requestMetricsData, setEndpoints, setGettingStartedEmptyState, } from '~/monitoring/stores/actions'; @@ -31,6 +29,7 @@ import { } from '../mock_data'; jest.mock('~/lib/utils/common_utils'); +jest.mock('~/flash'); const resetStore = str => { str.replaceState({ @@ -40,71 +39,36 @@ const resetStore = str => { }); }; -const MAX_REQUESTS = 3; - -describe('Monitoring store helpers', () => { +describe('Monitoring store actions', () => { let mock; - - // Mock underlying `backOff` function to remove in-built delay. - backOff.mockImplementation( - callback => - new Promise((resolve, reject) => { - const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg)); - const next = () => callback(next, stop); - callback(next, stop); - }), - ); - beforeEach(() => { mock = new MockAdapter(axios); - }); - - afterEach(() => { - mock.restore(); - }); - - describe('backOffRequest', () => { - it('returns immediately when recieving a 200 status code', () => { - mock.onGet(TEST_HOST).reply(200); - - return backOffRequest(() => axios.get(TEST_HOST)).then(() => { - expect(mock.history.get.length).toBe(1); - }); - }); - it(`repeats the network call ${MAX_REQUESTS} times when receiving a 204 response`, done => { - mock.onGet(TEST_HOST).reply(statusCodes.NO_CONTENT, {}); + // Mock `backOff` function to remove exponential algorithm delay. + jest.useFakeTimers(); - backOffRequest(() => axios.get(TEST_HOST)) - .then(done.fail) - .catch(() => { - expect(mock.history.get.length).toBe(MAX_REQUESTS); - done(); + backOff.mockImplementation(callback => { + const q = new Promise((resolve, reject) => { + const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg)); + const next = () => callback(next, stop); + // Define a timeout based on a mock timer + setTimeout(() => { + callback(next, stop); }); + }); + // Run all resolved promises in chain + jest.runOnlyPendingTimers(); + return q; }); }); -}); - -describe('Monitoring store actions', () => { - let mock; - beforeEach(() => { - mock = new MockAdapter(axios); - }); afterEach(() => { resetStore(store); - mock.restore(); - }); - describe('requestMetricsData', () => { - it('sets emptyState to loading', () => { - const commit = jest.fn(); - const { state } = store; - requestMetricsData({ - state, - commit, - }); - expect(commit).toHaveBeenCalledWith(types.REQUEST_METRICS_DATA); - }); + mock.reset(); + + backOff.mockReset(); + createFlash.mockReset(); }); + describe('fetchDeploymentsData', () => { it('commits RECEIVE_DEPLOYMENTS_DATA_SUCCESS on error', done => { const dispatch = jest.fn(); @@ -362,17 +326,11 @@ describe('Monitoring store actions', () => { it('commits empty state when state.groups is empty', done => { const state = storeState(); const params = {}; - fetchPrometheusMetrics( - { - state, - commit, - dispatch, - }, - params, - ) + fetchPrometheusMetrics({ state, commit, dispatch }, params) .then(() => { expect(commit).toHaveBeenCalledWith(types.SET_NO_DATA_EMPTY_STATE); expect(dispatch).not.toHaveBeenCalled(); + expect(createFlash).not.toHaveBeenCalled(); done(); }) .catch(done.fail); @@ -382,20 +340,42 @@ describe('Monitoring store actions', () => { const state = storeState(); state.dashboard.panel_groups = metricsDashboardResponse.dashboard.panel_groups; const metric = state.dashboard.panel_groups[0].panels[0].metrics[0]; - fetchPrometheusMetrics( - { - state, - commit, - dispatch, - }, - params, - ) + fetchPrometheusMetrics({ state, commit, dispatch }, params) + .then(() => { + expect(dispatch).toHaveBeenCalledTimes(3); + expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', { + metric, + params, + }); + + expect(createFlash).not.toHaveBeenCalled(); + + done(); + }) + .catch(done.fail); + done(); + }); + + it('dispatches fetchPrometheusMetric for each panel query, handles an error', done => { + const params = {}; + const state = storeState(); + state.dashboard.panel_groups = metricsDashboardResponse.dashboard.panel_groups; + const metric = state.dashboard.panel_groups[0].panels[0].metrics[0]; + + // Mock having one out of three metrics failing + dispatch.mockRejectedValueOnce(new Error('Error fetching this metric')); + dispatch.mockResolvedValue(); + + fetchPrometheusMetrics({ state, commit, dispatch }, params) .then(() => { expect(dispatch).toHaveBeenCalledTimes(3); expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetric', { metric, params, }); + + expect(createFlash).toHaveBeenCalledTimes(1); + done(); }) .catch(done.fail); @@ -403,28 +383,75 @@ describe('Monitoring store actions', () => { }); }); describe('fetchPrometheusMetric', () => { - it('commits prometheus query result', done => { - const commit = jest.fn(); - const params = { - start: '2019-08-06T12:40:02.184Z', - end: '2019-08-06T20:40:02.184Z', - }; - const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0]; - const state = storeState(); - const data = metricsGroupsAPIResponse[0].panels[0].metrics[0]; - const response = { - data, - }; - mock.onGet('http://test').reply(200, response); + const params = { + start: '2019-08-06T12:40:02.184Z', + end: '2019-08-06T20:40:02.184Z', + }; + let commit; + let metric; + let state; + let data; + + beforeEach(() => { + commit = jest.fn(); + state = storeState(); + [metric] = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics; + [data] = metricsGroupsAPIResponse[0].panels[0].metrics; + }); + + it('commits result', done => { + mock.onGet('http://test').reply(200, { data }); // One attempt + fetchPrometheusMetric({ state, commit }, { metric, params }) .then(() => { expect(commit).toHaveBeenCalledWith(types.SET_QUERY_RESULT, { metricId: metric.metric_id, result: data.result, }); + + expect(mock.history.get).toHaveLength(1); done(); }) .catch(done.fail); }); + + it('commits result, when waiting for results', done => { + // Mock multiple attempts while the cache is filling up + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').reply(200, { data }); // 4th attempt + + const fetch = fetchPrometheusMetric({ state, commit }, { metric, params }); + + fetch + .then(() => { + expect(commit).toHaveBeenCalledWith(types.SET_QUERY_RESULT, { + metricId: metric.metric_id, + result: data.result, + }); + expect(mock.history.get).toHaveLength(4); + done(); + }) + .catch(done.fail); + }); + + it('commits failure, when waiting for results and getting a server error', done => { + // Mock multiple attempts while the cache is filling up and fails + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').replyOnce(statusCodes.NO_CONTENT); + mock.onGet('http://test').reply(500); // 4th attempt + + fetchPrometheusMetric({ state, commit }, { metric, params }) + .then(() => { + done.fail(); + }) + .catch(() => { + expect(commit).not.toHaveBeenCalled(); + expect(mock.history.get).toHaveLength(4); + done(); + }); + }); }); }); |