Commit f7dfe54e authored by mfluharty's avatar mfluharty

Add codequality report specs and changelog

Add spec for the codequality_report vue app
Add tests for the codequality_report vuex store
parent 8db24c42
---
title: Add code quality tab to pipeline view
merge_request: 21527
author:
type: added
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { TEST_HOST } from 'helpers/test_constants';
import CodequalityReportApp from 'ee/codequality_report/codequality_report.vue';
import store from 'ee/codequality_report/store';
import { parsedIssues, unparsedIssues } from './mock_data';
import { mount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
jest.mock('~/flash', () => jest.fn());
describe('Codequality report app', () => {
let wrapper;
let mock;
const codequalityReportDownloadPath = `${TEST_HOST}/codequality_report`;
const createComponent = (props = {}) => {
wrapper = mount(CodequalityReportApp, {
store,
propsData: {
codequalityReportDownloadPath,
blobPath: '/root/test-codequality/blob/feature-branch',
...props,
},
});
};
const findStatus = () => wrapper.find('.js-code-text');
const findSuccessIcon = () => wrapper.find('.js-ci-status-icon-success');
const findWarningIcon = () => wrapper.find('.js-ci-status-icon-warning');
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
mock.restore();
});
describe('when loading', () => {
beforeEach(() => {
createComponent();
});
it('shows a loading state', () => {
expect(findStatus().text()).toBe('Loading codeclimate report');
});
});
describe('on error', () => {
beforeEach(() => {
mock.onGet(codequalityReportDownloadPath).reply(500);
createComponent();
return waitForPromises();
});
it('shows a warning icon and error message', () => {
expect(findWarningIcon().exists()).toBe(true);
expect(findStatus().text()).toBe('Failed to load codeclimate report');
});
it('shows a flash message', () => {
expect(createFlash).toHaveBeenCalled();
});
});
describe('when there are codequality issues', () => {
beforeEach(() => {
mock.onGet(codequalityReportDownloadPath).reply(200, unparsedIssues);
createComponent();
return waitForPromises();
});
it('renders the codequality issues', () => {
const expectedIssueTotal = parsedIssues.length;
expect(wrapper.vm.$store.state.allCodequalityIssues).toEqual(parsedIssues);
expect(findStatus().text()).toBe(`Found ${expectedIssueTotal} code quality issues`);
expect(wrapper.findAll('.report-block-list-issue').length).toBe(expectedIssueTotal);
});
});
describe('when there are no codequality issues', () => {
beforeEach(() => {
mock.onGet(codequalityReportDownloadPath).reply(200, []);
createComponent();
return waitForPromises();
});
it('shows a message that no codequality issues were found', () => {
expect(wrapper.vm.$store.state.allCodequalityIssues).toEqual([]);
expect(findSuccessIcon().exists()).toBe(true);
expect(findStatus().text()).toBe('No code quality issues found');
expect(wrapper.findAll('.report-block-list-issue').length).toBe(0);
});
});
});
This diff is collapsed.
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import * as actions from 'ee/codequality_report/store/actions';
import * as types from 'ee/codequality_report/store/mutation_types';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
import createFlash from '~/flash';
import { unparsedIssues, parsedIssues } from '../mock_data';
jest.mock('~/flash');
describe('Codequality report actions', () => {
let mock;
let state;
const endpoint = `${TEST_HOST}/codequality_report.json`;
const defaultState = {
endpoint,
};
beforeEach(() => {
mock = new MockAdapter(axios);
state = defaultState;
});
afterEach(() => {
mock.restore();
});
describe('setEndpoint', () => {
it('sets the endpoint', done => {
testAction(
actions.setEndpoint,
'endpoint',
state,
[{ type: types.SET_ENDPOINT, payload: 'endpoint' }],
[],
done,
);
});
});
describe('setBlobPath', () => {
it('sets the blob path', done => {
testAction(
actions.setBlobPath,
'blobPath',
state,
[{ type: types.SET_BLOB_PATH, payload: 'blobPath' }],
[],
done,
);
});
});
describe('setPage', () => {
it('sets the page number', done => {
testAction(actions.setPage, 12, state, [{ type: types.SET_PAGE, payload: 12 }], [], done);
});
});
describe('requestReport', () => {
it('sets the loading flag', done => {
testAction(actions.requestReport, null, state, [{ type: types.REQUEST_REPORT }], [], done);
});
});
describe('receiveReportSuccess', () => {
it('parses the list of issues from the report', done => {
testAction(
actions.receiveReportSuccess,
unparsedIssues,
{ blobPath: '/root/test-codequality/blob/feature-branch', ...state },
[{ type: types.RECEIVE_REPORT_SUCCESS, payload: parsedIssues }],
[],
done,
);
});
});
describe('receiveReportError', () => {
it('accepts a report error', done => {
testAction(
actions.receiveReportError,
'error',
state,
[{ type: types.RECEIVE_REPORT_ERROR, payload: 'error' }],
[],
done,
);
});
});
describe('fetchReport', () => {
beforeEach(() => {
mock.onGet(endpoint).replyOnce(200, unparsedIssues);
});
it('fetches the report', done => {
testAction(
actions.fetchReport,
null,
{ blobPath: 'blah', ...state },
[],
[{ type: 'requestReport' }, { type: 'receiveReportSuccess', payload: unparsedIssues }],
done,
);
});
it('shows a flash message when there is an error', done => {
testAction(
actions.fetchReport,
'error',
state,
[],
[{ type: 'requestReport' }, { type: 'receiveReportError', payload: new Error() }],
() => {
expect(createFlash).toHaveBeenCalledWith(
'There was an error fetching the codequality report.',
);
done();
},
);
});
it('shows an error when blob path is missing', done => {
testAction(
actions.fetchReport,
null,
state,
[],
[{ type: 'requestReport' }, { type: 'receiveReportError', payload: new Error() }],
() => {
expect(createFlash).toHaveBeenCalledWith(
'There was an error fetching the codequality report.',
);
done();
},
);
});
});
});
import * as getters from 'ee/codequality_report/store/getters';
import { parsedIssues } from '../mock_data';
describe('Codequality report getters', () => {
let state;
const defaultState = {
allCodequalityIssues: parsedIssues,
};
beforeEach(() => {
state = defaultState;
});
describe('codequalityIssues', () => {
it('gets the current page of issues', () => {
expect(
getters.codequalityIssues({ pageInfo: { page: 1, perPage: 2, total: 3 }, ...state }),
).toEqual(parsedIssues.slice(0, 2));
expect(
getters.codequalityIssues({ pageInfo: { page: 2, perPage: 2, total: 3 }, ...state }),
).toEqual(parsedIssues.slice(2, 3));
});
});
describe('codequalityIssueTotal', () => {
it('gets the total number of codequality issues', () => {
expect(getters.codequalityIssueTotal(state)).toBe(parsedIssues.length);
});
});
});
import * as types from 'ee/codequality_report/store/mutation_types';
import mutations from 'ee/codequality_report/store/mutations';
import { parsedIssues } from '../mock_data';
describe('Codequality report mutations', () => {
let state;
const defaultState = {
pageInfo: {},
};
beforeEach(() => {
state = defaultState;
});
describe('set endpoint', () => {
it('should set endpoint', () => {
mutations[types.SET_ENDPOINT](state, 'endpoint');
expect(state.endpoint).toBe('endpoint');
});
});
describe('set blob path', () => {
it('should set blob path', () => {
mutations[types.SET_BLOB_PATH](state, 'blobPath');
expect(state.blobPath).toBe('blobPath');
});
});
describe('set page', () => {
it('should set page', () => {
mutations[types.SET_PAGE](state, 4);
expect(state.pageInfo.page).toBe(4);
});
});
describe('request report', () => {
it('should set the loading flag', () => {
mutations[types.REQUEST_REPORT](state);
expect(state.isLoadingCodequality).toBe(true);
});
});
describe('receive report success', () => {
it('should set issue info and clear the loading flag', () => {
mutations[types.RECEIVE_REPORT_SUCCESS](state, parsedIssues);
expect(state.isLoadingCodequality).toBe(false);
expect(state.allCodequalityIssues).toBe(parsedIssues);
expect(state.pageInfo.total).toBe(parsedIssues.length);
});
});
describe('receive report error', () => {
it('should set error info and clear the loading flag', () => {
mutations[types.RECEIVE_REPORT_ERROR](state, new Error());
expect(state.isLoadingCodequality).toBe(false);
expect(state.loadingCodequalityFailed).toBe(true);
expect(state.allCodequalityIssues).toEqual([]);
expect(state.codeQualityError).toEqual(new Error());
expect(state.pageInfo.total).toBe(0);
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment