Commit 53c80aa2 authored by Frédéric Caplette's avatar Frédéric Caplette

Merge branch '299358-update-compliance-report-query-with-filter-variables' into 'master'

Update compliance report to sync filter query with apollo variables

See merge request gitlab-org/gitlab!78451
parents 815208ba 1555efde
......@@ -9,6 +9,7 @@ import UrlSync from '~/vue_shared/components/url_sync.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
import complianceViolationsQuery from '../graphql/compliance_violations.query.graphql';
import { mapViolations } from '../graphql/mappers';
import { parseViolationsQueryFilter } from '../utils';
import MergeCommitsExportButton from './merge_requests/merge_commits_export_button.vue';
import MergeRequestDrawer from './drawer.vue';
import ViolationReason from './violations/reason.vue';
......@@ -45,7 +46,7 @@ export default {
},
data() {
return {
urlQuery: {},
urlQuery: { ...this.defaultQuery },
queryError: false,
violations: [],
showDrawer: false,
......@@ -58,7 +59,8 @@ export default {
query: complianceViolationsQuery,
variables() {
return {
fullPath: 'groups-path',
fullPath: this.groupPath,
filter: parseViolationsQueryFilter(this.urlQuery),
};
},
update(data) {
......
query getComplianceViolations($fullPath: ID!) {
group(fullPath: $fullPath) @client {
# TODO: Add the correct filter type once it has been added in https://gitlab.com/gitlab-org/gitlab/-/issues/347325
query getComplianceViolations($fullPath: ID!, $filter: Object) {
group(fullPath: $fullPath, filter: $filter) @client {
id
mergeRequestViolations {
nodes {
......
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { convertToGraphQLIds } from '~/graphql_shared/utils';
import { TYPE_PROJECT } from '~/graphql_shared/constants';
import { formatDate } from '~/lib/utils/datetime_utility';
import { ISO_SHORT_FORMAT } from '~/vue_shared/constants';
export const mapDashboardToDrawerData = (mergeRequest) => ({
id: mergeRequest.id,
......@@ -21,3 +23,9 @@ export const convertProjectIdsToGraphQl = (projectIds) =>
TYPE_PROJECT,
projectIds.filter((id) => Boolean(id)),
);
export const parseViolationsQueryFilter = ({ createdBefore, createdAfter, projectIds }) => ({
projectIds: projectIds ? convertProjectIdsToGraphQl(projectIds) : [],
createdBefore: formatDate(createdBefore, ISO_SHORT_FORMAT),
createdAfter: formatDate(createdAfter, ISO_SHORT_FORMAT),
});
......@@ -17,6 +17,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { stubComponent } from 'helpers/stub_component';
import { parseViolationsQueryFilter } from 'ee/compliance_dashboard/utils';
Vue.use(VueApollo);
......@@ -26,10 +27,12 @@ describe('ComplianceReport component', () => {
const mergeCommitsCsvExportPath = '/csv';
const groupPath = 'group-path';
const createdAfter = '2021-11-16';
const createdBefore = '2021-12-15';
const defaultQuery = {
projectIds: ['gid://gitlab/Project/20'],
createdAfter: '2021-11-16',
createdBefore: '2021-12-15',
projectIds: ['20'],
createdAfter,
createdBefore,
};
const mockGraphQlError = new Error('GraphQL networkError');
......@@ -54,6 +57,13 @@ describe('ComplianceReport component', () => {
await nextTick();
};
const expectApolloVariables = (variables) => [
{},
variables,
expect.anything(),
expect.anything(),
];
function createMockApolloProvider() {
return createMockApollo([], { Query: { group: mockResolver } });
}
......@@ -110,6 +120,7 @@ describe('ComplianceReport component', () => {
describe('when initializing', () => {
beforeEach(() => {
mockResolver = jest.fn();
wrapper = createComponent(mount);
});
......@@ -117,6 +128,16 @@ describe('ComplianceReport component', () => {
expect(findViolationsTable().exists()).toBe(true);
expect(findTableLoadingIcon().exists()).toBe(true);
});
it('fetches the list of merge request violations with the filter query', async () => {
expect(mockResolver).toHaveBeenCalledTimes(1);
expect(mockResolver).toHaveBeenCalledWith(
...expectApolloVariables({
fullPath: groupPath,
filter: parseViolationsQueryFilter(defaultQuery),
}),
);
});
});
describe('when the query fails', () => {
......@@ -244,6 +265,13 @@ describe('ComplianceReport component', () => {
});
describe('violation filter', () => {
beforeEach(() => {
mockResolver = jest.fn().mockReturnValue(resolvers.Query.group());
wrapper = createComponent(mount);
return waitForPromises();
});
it('configures the filter', () => {
expect(findViolationFilter().props()).toMatchObject({
groupPath,
......@@ -251,20 +279,37 @@ describe('ComplianceReport component', () => {
});
});
it('updates the URL query when the filters changed', async () => {
const query = { foo: 'bar', projectIds: [1, 2, 3] };
describe('when the filters changed', () => {
const query = { createdAfter, createdBefore, projectIds: [1, 2, 3] };
await findViolationFilter().vm.$emit('filters-changed', query);
beforeEach(() => {
return findViolationFilter().vm.$emit('filters-changed', query);
});
expect(findUrlSync().props('query')).toMatchObject(query);
});
it('updates the URL query', () => {
expect(findUrlSync().props('query')).toMatchObject(query);
});
it('clears the project URL query param when the filters changed and the project array is empty', async () => {
const query = { foo: 'bar', projectIds: [] };
it('shows the table loading icon', () => {
expect(findTableLoadingIcon().exists()).toBe(true);
});
await findViolationFilter().vm.$emit('filters-changed', query);
it('clears the project URL query param if the project array is empty', async () => {
await findViolationFilter().vm.$emit('filters-changed', { ...query, projectIds: [] });
expect(findUrlSync().props('query')).toMatchObject({ ...query, projectIds: null });
expect(findUrlSync().props('query')).toMatchObject({ ...query, projectIds: null });
});
it('fetches the filtered violations', async () => {
expect(mockResolver).toHaveBeenCalledTimes(2);
expect(mockResolver).toHaveBeenNthCalledWith(
2,
...expectApolloVariables({
fullPath: groupPath,
filter: parseViolationsQueryFilter(query),
}),
);
});
});
});
});
......
import * as utils from 'ee/compliance_dashboard/utils';
describe('compliance report utils', () => {
const projectIds = ['1', '2'];
const projectGraphQlIds = ['gid://gitlab/Project/1', 'gid://gitlab/Project/2'];
describe('parseViolationsQueryFilter', () => {
it('returns the expected result', () => {
const query = {
projectIds,
createdAfter: '2021-12-06',
createdBefore: '2022-01-06',
};
expect(utils.parseViolationsQueryFilter(query)).toStrictEqual({
projectIds: projectGraphQlIds,
createdAfter: query.createdAfter,
createdBefore: query.createdBefore,
});
});
});
describe('convertProjectIdsToGraphQl', () => {
it('returns the expected result', () => {
expect(utils.convertProjectIdsToGraphQl(['1', '2'])).toStrictEqual([
'gid://gitlab/Project/1',
'gid://gitlab/Project/2',
]);
expect(utils.convertProjectIdsToGraphQl(projectIds)).toStrictEqual(projectGraphQlIds);
});
});
});
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