Commit e29c9311 authored by Savas Vedova's avatar Savas Vedova

Merge branch 'frontend-code-quality-cleanup' into 'master'

Remove frontend code quality comparison

See merge request gitlab-org/gitlab!55708
parents 88c8edbf 38022fb8
...@@ -3,7 +3,6 @@ import { mapState, mapActions, mapGetters } from 'vuex'; ...@@ -3,7 +3,6 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import { componentNames } from '~/reports/components/issue_body'; import { componentNames } from '~/reports/components/issue_body';
import ReportSection from '~/reports/components/report_section.vue'; import ReportSection from '~/reports/components/report_section.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import createStore from './store'; import createStore from './store';
export default { export default {
...@@ -12,26 +11,12 @@ export default { ...@@ -12,26 +11,12 @@ export default {
components: { components: {
ReportSection, ReportSection,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
headPath: {
type: String,
required: true,
},
headBlobPath: {
type: String,
required: true,
},
basePath: { basePath: {
type: String, type: String,
required: false, required: false,
default: null, default: null,
}, },
baseBlobPath: {
type: String,
required: false,
default: null,
},
codequalityReportsPath: { codequalityReportsPath: {
type: String, type: String,
required: false, required: false,
...@@ -55,9 +40,6 @@ export default { ...@@ -55,9 +40,6 @@ export default {
created() { created() {
this.setPaths({ this.setPaths({
basePath: this.basePath, basePath: this.basePath,
headPath: this.headPath,
baseBlobPath: this.baseBlobPath,
headBlobPath: this.headBlobPath,
reportsPath: this.codequalityReportsPath, reportsPath: this.codequalityReportsPath,
helpPath: this.codequalityHelpPath, helpPath: this.codequalityHelpPath,
}); });
......
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { parseCodeclimateMetrics, doCodeClimateComparison } from './utils/codequality_comparison'; import { parseCodeclimateMetrics } from './utils/codequality_parser';
export const setPaths = ({ commit }, paths) => commit(types.SET_PATHS, paths); export const setPaths = ({ commit }, paths) => commit(types.SET_PATHS, paths);
export const fetchReports = ({ state, dispatch, commit }, diffFeatureFlagEnabled) => { export const fetchReports = ({ state, dispatch, commit }) => {
commit(types.REQUEST_REPORTS); commit(types.REQUEST_REPORTS);
if (diffFeatureFlagEnabled) {
return axios
.get(state.reportsPath)
.then(({ data }) => {
return dispatch('receiveReportsSuccess', {
newIssues: parseCodeclimateMetrics(data.new_errors, state.headBlobPath),
resolvedIssues: parseCodeclimateMetrics(data.resolved_errors, state.baseBlobPath),
});
})
.catch((error) => dispatch('receiveReportsError', error));
}
if (!state.basePath) { if (!state.basePath) {
return dispatch('receiveReportsError'); return dispatch('receiveReportsError');
} }
return Promise.all([axios.get(state.headPath), axios.get(state.basePath)]) return axios
.then((results) => .get(state.reportsPath)
doCodeClimateComparison( .then(({ data }) => {
parseCodeclimateMetrics(results[0].data, state.headBlobPath), return dispatch('receiveReportsSuccess', {
parseCodeclimateMetrics(results[1].data, state.baseBlobPath), newIssues: parseCodeclimateMetrics(data.new_errors, state.headBlobPath),
), resolvedIssues: parseCodeclimateMetrics(data.resolved_errors, state.baseBlobPath),
) });
.then((data) => dispatch('receiveReportsSuccess', data)) })
.catch((error) => dispatch('receiveReportsError', error)); .catch((error) => dispatch('receiveReportsError', error));
}; };
......
...@@ -3,9 +3,6 @@ import * as types from './mutation_types'; ...@@ -3,9 +3,6 @@ import * as types from './mutation_types';
export default { export default {
[types.SET_PATHS](state, paths) { [types.SET_PATHS](state, paths) {
state.basePath = paths.basePath; state.basePath = paths.basePath;
state.headPath = paths.headPath;
state.baseBlobPath = paths.baseBlobPath;
state.headBlobPath = paths.headBlobPath;
state.reportsPath = paths.reportsPath; state.reportsPath = paths.reportsPath;
state.helpPath = paths.helpPath; state.helpPath = paths.helpPath;
}, },
......
import CodeQualityComparisonWorker from '../../workers/codequality_comparison_worker';
export const parseCodeclimateMetrics = (issues = [], path = '') => { export const parseCodeclimateMetrics = (issues = [], path = '') => {
return issues.map((issue) => { return issues.map((issue) => {
const parsedIssue = { const parsedIssue = {
...@@ -27,17 +25,3 @@ export const parseCodeclimateMetrics = (issues = [], path = '') => { ...@@ -27,17 +25,3 @@ export const parseCodeclimateMetrics = (issues = [], path = '') => {
return parsedIssue; return parsedIssue;
}); });
}; };
export const doCodeClimateComparison = (headIssues, baseIssues) => {
// Do these comparisons in worker threads to avoid blocking the main thread
return new Promise((resolve, reject) => {
const worker = new CodeQualityComparisonWorker();
worker.addEventListener('message', ({ data }) =>
data.newIssues && data.resolvedIssues ? resolve(data) : reject(data),
);
worker.postMessage({
headIssues,
baseIssues,
});
});
};
import { differenceBy } from 'lodash';
const KEY_TO_FILTER_BY = 'fingerprint';
// eslint-disable-next-line no-restricted-globals
self.addEventListener('message', (e) => {
const { data } = e;
if (data === undefined) {
return null;
}
const { headIssues, baseIssues } = data;
if (!headIssues || !baseIssues) {
// eslint-disable-next-line no-restricted-globals
return self.postMessage({});
}
// eslint-disable-next-line no-restricted-globals
self.postMessage({
newIssues: differenceBy(headIssues, baseIssues, KEY_TO_FILTER_BY),
resolvedIssues: differenceBy(baseIssues, headIssues, KEY_TO_FILTER_BY),
});
// eslint-disable-next-line no-restricted-globals
return self.close();
});
...@@ -460,9 +460,6 @@ export default { ...@@ -460,9 +460,6 @@ export default {
<grouped-codequality-reports-app <grouped-codequality-reports-app
v-if="shouldRenderCodeQuality" v-if="shouldRenderCodeQuality"
:base-path="mr.codeclimate.base_path" :base-path="mr.codeclimate.base_path"
:head-path="mr.codeclimate.head_path"
:head-blob-path="mr.headBlobPath"
:base-blob-path="mr.baseBlobPath"
:codequality-reports-path="mr.codequalityReportsPath" :codequality-reports-path="mr.codequalityReportsPath"
:codequality-help-path="mr.codequalityHelpPath" :codequality-help-path="mr.codequalityHelpPath"
/> />
......
...@@ -3,7 +3,7 @@ import createFlash from '~/flash'; ...@@ -3,7 +3,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { parseCodeclimateMetrics } from '~/reports/codequality_report/store/utils/codequality_comparison'; import { parseCodeclimateMetrics } from '~/reports/codequality_report/store/utils/codequality_parser';
import { VIEW_EVENT_FEATURE_FLAG, VIEW_EVENT_NAME } from './constants'; import { VIEW_EVENT_FEATURE_FLAG, VIEW_EVENT_NAME } from './constants';
import * as types from './mutation_types'; import * as types from './mutation_types';
......
...@@ -279,9 +279,6 @@ export default { ...@@ -279,9 +279,6 @@ export default {
<grouped-codequality-reports-app <grouped-codequality-reports-app
v-if="shouldRenderCodeQuality" v-if="shouldRenderCodeQuality"
:base-path="mr.codeclimate.base_path" :base-path="mr.codeclimate.base_path"
:head-path="mr.codeclimate.head_path"
:head-blob-path="mr.headBlobPath"
:base-blob-path="mr.baseBlobPath"
:codequality-reports-path="mr.codequalityReportsPath" :codequality-reports-path="mr.codequalityReportsPath"
:codequality-help-path="mr.codequalityHelpPath" :codequality-help-path="mr.codequalityHelpPath"
/> />
......
...@@ -3,7 +3,7 @@ import Vuex from 'vuex'; ...@@ -3,7 +3,7 @@ import Vuex from 'vuex';
import CodequalityIssueBody from '~/reports/codequality_report/components/codequality_issue_body.vue'; import CodequalityIssueBody from '~/reports/codequality_report/components/codequality_issue_body.vue';
import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue'; import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue';
import { getStoreConfig } from '~/reports/codequality_report/store'; import { getStoreConfig } from '~/reports/codequality_report/store';
import { mockParsedHeadIssues, mockParsedBaseIssues } from './mock_data'; import { parsedReportIssues } from './mock_data';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
...@@ -80,7 +80,7 @@ describe('Grouped code quality reports app', () => { ...@@ -80,7 +80,7 @@ describe('Grouped code quality reports app', () => {
describe('with issues', () => { describe('with issues', () => {
describe('with new issues', () => { describe('with new issues', () => {
beforeEach(() => { beforeEach(() => {
mockStore.state.newIssues = [mockParsedHeadIssues[0]]; mockStore.state.newIssues = parsedReportIssues.newIssues;
mockStore.state.resolvedIssues = []; mockStore.state.resolvedIssues = [];
}); });
...@@ -89,14 +89,14 @@ describe('Grouped code quality reports app', () => { ...@@ -89,14 +89,14 @@ describe('Grouped code quality reports app', () => {
}); });
it('renders custom codequality issue body', () => { it('renders custom codequality issue body', () => {
expect(findIssueBody().props('issue')).toEqual(mockParsedHeadIssues[0]); expect(findIssueBody().props('issue')).toEqual(parsedReportIssues.newIssues[0]);
}); });
}); });
describe('with resolved issues', () => { describe('with resolved issues', () => {
beforeEach(() => { beforeEach(() => {
mockStore.state.newIssues = []; mockStore.state.newIssues = [];
mockStore.state.resolvedIssues = [mockParsedBaseIssues[0]]; mockStore.state.resolvedIssues = parsedReportIssues.resolvedIssues;
}); });
it('renders summary text', () => { it('renders summary text', () => {
...@@ -104,14 +104,14 @@ describe('Grouped code quality reports app', () => { ...@@ -104,14 +104,14 @@ describe('Grouped code quality reports app', () => {
}); });
it('renders custom codequality issue body', () => { it('renders custom codequality issue body', () => {
expect(findIssueBody().props('issue')).toEqual(mockParsedBaseIssues[0]); expect(findIssueBody().props('issue')).toEqual(parsedReportIssues.resolvedIssues[0]);
}); });
}); });
describe('with new and resolved issues', () => { describe('with new and resolved issues', () => {
beforeEach(() => { beforeEach(() => {
mockStore.state.newIssues = [mockParsedHeadIssues[0]]; mockStore.state.newIssues = parsedReportIssues.newIssues;
mockStore.state.resolvedIssues = [mockParsedBaseIssues[0]]; mockStore.state.resolvedIssues = parsedReportIssues.resolvedIssues;
}); });
it('renders summary text', () => { it('renders summary text', () => {
...@@ -121,7 +121,7 @@ describe('Grouped code quality reports app', () => { ...@@ -121,7 +121,7 @@ describe('Grouped code quality reports app', () => {
}); });
it('renders custom codequality issue body', () => { it('renders custom codequality issue body', () => {
expect(findIssueBody().props('issue')).toEqual(mockParsedHeadIssues[0]); expect(findIssueBody().props('issue')).toEqual(parsedReportIssues.newIssues[0]);
}); });
}); });
}); });
......
export const headIssues = [
{
check_name: 'Rubocop/Lint/UselessAssignment',
description: 'Insecure Dependency',
location: {
path: 'lib/six.rb',
lines: {
begin: 6,
end: 7,
},
},
fingerprint: 'e879dd9bbc0953cad5037cde7ff0f627',
},
{
categories: ['Security'],
check_name: 'Insecure Dependency',
description: 'Insecure Dependency',
location: {
path: 'Gemfile.lock',
lines: {
begin: 22,
end: 22,
},
},
fingerprint: 'ca2e59451e98ae60ba2f54e3857c50e5',
},
];
export const mockParsedHeadIssues = [
{
...headIssues[1],
name: 'Insecure Dependency',
path: 'lib/six.rb',
urlPath: 'headPath/lib/six.rb#L6',
line: 6,
},
];
export const baseIssues = [
{
categories: ['Security'],
check_name: 'Insecure Dependency',
description: 'Insecure Dependency',
location: {
path: 'Gemfile.lock',
lines: {
begin: 22,
end: 22,
},
},
fingerprint: 'ca2e59451e98ae60ba2f54e3857c50e5',
},
{
categories: ['Security'],
check_name: 'Insecure Dependency',
description: 'Insecure Dependency',
location: {
path: 'Gemfile.lock',
lines: {
begin: 21,
end: 21,
},
},
fingerprint: 'ca2354534dee94ae60ba2f54e3857c50e5',
},
];
export const mockParsedBaseIssues = [
{
...baseIssues[1],
name: 'Insecure Dependency',
path: 'Gemfile.lock',
line: 21,
urlPath: 'basePath/Gemfile.lock#L21',
},
];
export const issueDiff = [
{
categories: ['Security'],
check_name: 'Insecure Dependency',
description: 'Insecure Dependency',
fingerprint: 'ca2e59451e98ae60ba2f54e3857c50e5',
line: 6,
location: { lines: { begin: 22, end: 22 }, path: 'Gemfile.lock' },
name: 'Insecure Dependency',
path: 'lib/six.rb',
urlPath: 'headPath/lib/six.rb#L6',
},
];
export const reportIssues = { export const reportIssues = {
status: 'failed', status: 'failed',
new_errors: [ new_errors: [
......
...@@ -5,30 +5,7 @@ import axios from '~/lib/utils/axios_utils'; ...@@ -5,30 +5,7 @@ import axios from '~/lib/utils/axios_utils';
import createStore from '~/reports/codequality_report/store'; import createStore from '~/reports/codequality_report/store';
import * as actions from '~/reports/codequality_report/store/actions'; import * as actions from '~/reports/codequality_report/store/actions';
import * as types from '~/reports/codequality_report/store/mutation_types'; import * as types from '~/reports/codequality_report/store/mutation_types';
import { import { reportIssues, parsedReportIssues } from '../mock_data';
headIssues,
baseIssues,
mockParsedHeadIssues,
mockParsedBaseIssues,
reportIssues,
parsedReportIssues,
} from '../mock_data';
// mock codequality comparison worker
jest.mock('~/reports/codequality_report/workers/codequality_comparison_worker', () =>
jest.fn().mockImplementation(() => {
return {
addEventListener: (eventName, callback) => {
callback({
data: {
newIssues: [mockParsedHeadIssues[0]],
resolvedIssues: [mockParsedBaseIssues[0]],
},
});
},
};
}),
);
describe('Codequality Reports actions', () => { describe('Codequality Reports actions', () => {
let localState; let localState;
...@@ -43,9 +20,6 @@ describe('Codequality Reports actions', () => { ...@@ -43,9 +20,6 @@ describe('Codequality Reports actions', () => {
it('should commit SET_PATHS mutation', (done) => { it('should commit SET_PATHS mutation', (done) => {
const paths = { const paths = {
basePath: 'basePath', basePath: 'basePath',
headPath: 'headPath',
baseBlobPath: 'baseBlobPath',
headBlobPath: 'headBlobPath',
reportsPath: 'reportsPath', reportsPath: 'reportsPath',
helpPath: 'codequalityHelpPath', helpPath: 'codequalityHelpPath',
}; };
...@@ -63,119 +37,64 @@ describe('Codequality Reports actions', () => { ...@@ -63,119 +37,64 @@ describe('Codequality Reports actions', () => {
describe('fetchReports', () => { describe('fetchReports', () => {
let mock; let mock;
let diffFeatureFlagEnabled;
describe('with codequalityBackendComparison feature flag enabled', () => { beforeEach(() => {
beforeEach(() => { localState.reportsPath = `${TEST_HOST}/codequality_reports.json`;
diffFeatureFlagEnabled = true; localState.basePath = '/base/path';
localState.reportsPath = `${TEST_HOST}/codequality_reports.json`; mock = new MockAdapter(axios);
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
describe('on success', () => {
it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => {
mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(200, reportIssues);
testAction(
actions.fetchReports,
diffFeatureFlagEnabled,
localState,
[{ type: types.REQUEST_REPORTS }],
[
{
payload: parsedReportIssues,
type: 'receiveReportsSuccess',
},
],
done,
);
});
});
describe('on error', () => {
it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(500);
testAction(
actions.fetchReports,
diffFeatureFlagEnabled,
localState,
[{ type: types.REQUEST_REPORTS }],
[{ type: 'receiveReportsError', payload: expect.any(Error) }],
done,
);
});
});
}); });
describe('with codequalityBackendComparison feature flag disabled', () => { afterEach(() => {
beforeEach(() => { mock.restore();
diffFeatureFlagEnabled = false; });
localState.headPath = `${TEST_HOST}/head.json`;
localState.basePath = `${TEST_HOST}/base.json`;
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
describe('on success', () => { describe('on success', () => {
it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => { it('commits REQUEST_REPORTS and dispatches receiveReportsSuccess', (done) => {
mock.onGet(`${TEST_HOST}/head.json`).reply(200, headIssues); mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(200, reportIssues);
mock.onGet(`${TEST_HOST}/base.json`).reply(200, baseIssues);
testAction(
testAction( actions.fetchReports,
actions.fetchReports, null,
diffFeatureFlagEnabled, localState,
localState, [{ type: types.REQUEST_REPORTS }],
[{ type: types.REQUEST_REPORTS }], [
[ {
{ payload: parsedReportIssues,
payload: { type: 'receiveReportsSuccess',
newIssues: [mockParsedHeadIssues[0]], },
resolvedIssues: [mockParsedBaseIssues[0]], ],
}, done,
type: 'receiveReportsSuccess', );
},
],
done,
);
});
}); });
});
describe('on error', () => { describe('on error', () => {
it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => { it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
mock.onGet(`${TEST_HOST}/head.json`).reply(500); mock.onGet(`${TEST_HOST}/codequality_reports.json`).reply(500);
testAction( testAction(
actions.fetchReports, actions.fetchReports,
diffFeatureFlagEnabled, null,
localState, localState,
[{ type: types.REQUEST_REPORTS }], [{ type: types.REQUEST_REPORTS }],
[{ type: 'receiveReportsError', payload: expect.any(Error) }], [{ type: 'receiveReportsError', payload: expect.any(Error) }],
done, done,
); );
});
}); });
});
describe('with no base path', () => { describe('with no base path', () => {
it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => { it('commits REQUEST_REPORTS and dispatches receiveReportsError', (done) => {
localState.basePath = null; localState.basePath = null;
testAction( testAction(
actions.fetchReports, actions.fetchReports,
diffFeatureFlagEnabled, null,
localState, localState,
[{ type: types.REQUEST_REPORTS }], [{ type: types.REQUEST_REPORTS }],
[{ type: 'receiveReportsError' }], [{ type: 'receiveReportsError' }],
done, done,
); );
});
}); });
}); });
}); });
......
...@@ -13,23 +13,17 @@ describe('Codequality Reports mutations', () => { ...@@ -13,23 +13,17 @@ describe('Codequality Reports mutations', () => {
describe('SET_PATHS', () => { describe('SET_PATHS', () => {
it('sets paths to given values', () => { it('sets paths to given values', () => {
const basePath = 'base.json'; const basePath = 'base.json';
const headPath = 'head.json'; const reportsPath = 'reports.json';
const baseBlobPath = 'base/blob/path/';
const headBlobPath = 'head/blob/path/';
const helpPath = 'help.html'; const helpPath = 'help.html';
mutations.SET_PATHS(localState, { mutations.SET_PATHS(localState, {
basePath, basePath,
headPath, reportsPath,
baseBlobPath,
headBlobPath,
helpPath, helpPath,
}); });
expect(localState.basePath).toEqual(basePath); expect(localState.basePath).toEqual(basePath);
expect(localState.headPath).toEqual(headPath); expect(localState.reportsPath).toEqual(reportsPath);
expect(localState.baseBlobPath).toEqual(baseBlobPath);
expect(localState.headBlobPath).toEqual(headBlobPath);
expect(localState.helpPath).toEqual(helpPath); expect(localState.helpPath).toEqual(helpPath);
}); });
}); });
......
import { import { reportIssues, parsedReportIssues } from 'jest/reports/codequality_report/mock_data';
parseCodeclimateMetrics, import { parseCodeclimateMetrics } from '~/reports/codequality_report/store/utils/codequality_parser';
doCodeClimateComparison,
} from '~/reports/codequality_report/store/utils/codequality_comparison';
import {
baseIssues,
mockParsedHeadIssues,
mockParsedBaseIssues,
reportIssues,
parsedReportIssues,
} from '../../mock_data';
jest.mock('~/reports/codequality_report/workers/codequality_comparison_worker', () => {
let mockPostMessageCallback;
return jest.fn().mockImplementation(() => {
return {
addEventListener: (_, callback) => {
mockPostMessageCallback = callback;
},
postMessage: (data) => {
if (!data.headIssues) return mockPostMessageCallback({ data: {} });
if (!data.baseIssues) throw new Error();
const key = 'fingerprint';
return mockPostMessageCallback({
data: {
newIssues: data.headIssues.filter(
(item) => !data.baseIssues.find((el) => el[key] === item[key]),
),
resolvedIssues: data.baseIssues.filter(
(item) => !data.headIssues.find((el) => el[key] === item[key]),
),
},
});
},
};
});
});
describe('Codequality report store utils', () => { describe('Codequality report store utils', () => {
let result; let result;
describe('parseCodeclimateMetrics', () => { describe('parseCodeclimateMetrics', () => {
it('should parse the issues from codeclimate artifacts', () => {
[result] = parseCodeclimateMetrics(baseIssues, 'path');
expect(result.name).toEqual(baseIssues[0].check_name);
expect(result.path).toEqual(baseIssues[0].location.path);
expect(result.line).toEqual(baseIssues[0].location.lines.begin);
});
it('should parse the issues from backend codequality diff', () => { it('should parse the issues from backend codequality diff', () => {
[result] = parseCodeclimateMetrics(reportIssues.new_errors, 'path'); [result] = parseCodeclimateMetrics(reportIssues.new_errors, 'path');
...@@ -114,40 +71,4 @@ describe('Codequality report store utils', () => { ...@@ -114,40 +71,4 @@ describe('Codequality report store utils', () => {
}); });
}); });
}); });
describe('doCodeClimateComparison', () => {
describe('when the comparison worker finds changed issues', () => {
beforeEach(async () => {
result = await doCodeClimateComparison(mockParsedHeadIssues, mockParsedBaseIssues);
});
it('returns the new and resolved issues', () => {
expect(result.resolvedIssues[0]).toEqual(mockParsedBaseIssues[0]);
expect(result.newIssues[0]).toEqual(mockParsedHeadIssues[0]);
});
});
describe('when the comparison worker finds no changed issues', () => {
beforeEach(async () => {
result = await doCodeClimateComparison([], []);
});
it('returns the empty issue arrays', () => {
expect(result.newIssues).toEqual([]);
expect(result.resolvedIssues).toEqual([]);
});
});
describe('when the comparison worker is given malformed data', () => {
it('rejects the promise', () => {
return expect(doCodeClimateComparison(null)).rejects.toEqual({});
});
});
describe('when the comparison worker encounters an error', () => {
it('rejects the promise and throws an error', () => {
return expect(doCodeClimateComparison([], null)).rejects.toThrow();
});
});
});
}); });
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