Commit 034f2824 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '219402-geo-generic-graphql' into 'master'

Geo Generalization - GraphQL Query

Closes #219402

See merge request gitlab-org/gitlab!35788
parents f8ab8d57 5b710dbd
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
query($first: Int, $last: Int, $before: String!, $after: String!) {
geoNode {
packageFileRegistries(first: $first, last: $last, before: $before, after: $after) {
pageInfo {
...PageInfo
}
edges {
cursor
node {
id
packageFileId
state
retryCount
lastSyncFailure
retryAt
lastSyncedAt
createdAt
}
}
}
}
}
import gql from 'graphql-tag';
import PageInfo from '~/graphql_shared/fragments/pageInfo.fragment.graphql';
export default graphQlFieldName => {
return gql`
query($first: Int, $last: Int, $before: String!, $after: String!) {
geoNode {
${graphQlFieldName}(first: $first, last: $last, before: $before, after: $after) {
pageInfo {
...PageInfo
}
edges {
node {
id
packageFileId
state
retryCount
lastSyncFailure
retryAt
lastSyncedAt
createdAt
}
}
}
}
}
${PageInfo}
`;
};
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import { parseBoolean } from '~/lib/utils/common_utils';
import createStore from './store';
import GeoReplicableApp from './components/app.vue';
......@@ -8,12 +7,16 @@ Vue.use(Translate);
export default () => {
const el = document.getElementById('js-geo-replicable');
const { replicableType, geoTroubleshootingLink, geoReplicableEmptySvgPath } = el.dataset;
const useGraphQl = parseBoolean(el.dataset.graphql);
const {
replicableType,
geoTroubleshootingLink,
geoReplicableEmptySvgPath,
graphqlFieldName,
} = el.dataset;
return new Vue({
el,
store: createStore({ replicableType, useGraphQl }),
store: createStore({ replicableType, graphqlFieldName }),
components: {
GeoReplicableApp,
},
......
......@@ -7,7 +7,7 @@ import {
normalizeHeaders,
convertObjectPropsToCamelCase,
} from '~/lib/utils/common_utils';
import packageFilesQuery from '../graphql/package_files.query.graphql';
import buildReplicableTypeQuery from '../graphql/replicable_type_query_builder';
import { gqClient } from '../utils';
import * as types from './mutation_types';
import { FILTER_STATES, PREV, NEXT, DEFAULT_PAGE_SIZE } from '../constants';
......@@ -51,7 +51,7 @@ export const fetchReplicableItemsGraphQl = ({ state, dispatch }, direction) => {
gqClient
.query({
query: packageFilesQuery,
query: buildReplicableTypeQuery(state.graphqlFieldName),
variables: { first, last, before, after },
})
.then(res => {
......
......@@ -7,11 +7,11 @@ import createState from './state';
Vue.use(Vuex);
const createStore = ({ replicableType, useGraphQl }) =>
const createStore = ({ replicableType, graphqlFieldName }) =>
new Vuex.Store({
actions,
getters,
mutations,
state: createState({ replicableType, useGraphQl }),
state: createState({ replicableType, graphqlFieldName }),
});
export default createStore;
import { FILTER_STATES, DEFAULT_PAGE_SIZE } from '../constants';
const createState = ({ replicableType, useGraphQl }) => ({
const createState = ({ replicableType, graphqlFieldName }) => ({
replicableType,
useGraphQl,
graphqlFieldName,
useGraphQl: Boolean(graphqlFieldName),
isLoading: false,
replicableItems: [],
......
......@@ -3,4 +3,4 @@
#js-geo-replicable{ data: { "geo-replicable-empty-svg-path" => image_path("illustrations/empty-state/geo-replication-empty.svg"),
"geo-troubleshooting-link" => help_page_path("administration/geo/replication/troubleshooting.md"),
"replicable-type" => "package_files",
"graphql" => "true" } }
"graphql-field-name" => 'packageFileRegistries'} }
......@@ -2,7 +2,7 @@ import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import GeoReplicableApp from 'ee/geo_replicable/components/app.vue';
import createStore from 'ee/geo_replicable/store';
import initStore from 'ee/geo_replicable/store';
import GeoReplicable from 'ee/geo_replicable/components/geo_replicable.vue';
import GeoReplicableEmptyState from 'ee/geo_replicable/components/geo_replicable_empty_state.vue';
import GeoReplicableFilterBar from 'ee/geo_replicable/components/geo_replicable_filter_bar.vue';
......@@ -11,6 +11,7 @@ import {
MOCK_GEO_TROUBLESHOOTING_LINK,
MOCK_BASIC_FETCH_DATA_MAP,
MOCK_REPLICABLE_TYPE,
MOCK_GRAPHQL_REGISTRY,
} from '../mock_data';
const localVue = createLocalVue();
......@@ -18,25 +19,23 @@ localVue.use(Vuex);
describe('GeoReplicableApp', () => {
let wrapper;
let store;
const propsData = {
geoTroubleshootingLink: MOCK_GEO_TROUBLESHOOTING_LINK,
geoReplicableEmptySvgPath: MOCK_GEO_REPLICATION_SVG_PATH,
};
const actionSpies = {
fetchReplicableItems: jest.fn(),
setEndpoint: jest.fn(),
const createStore = options => {
store = initStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null, ...options });
jest.spyOn(store, 'dispatch').mockImplementation();
};
const createComponent = () => {
wrapper = shallowMount(GeoReplicableApp, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store,
propsData,
methods: {
...actionSpies,
},
});
};
......@@ -53,20 +52,20 @@ describe('GeoReplicableApp', () => {
findGeoReplicableContainer().find(GeoReplicableFilterBar);
describe.each`
isLoading | useGraphQl | replicableItems | showReplicableItems | showEmptyState | showFilterBar | showLoader
${false} | ${false} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${true} | ${false} | ${true} | ${false}
${false} | ${false} | ${[]} | ${false} | ${true} | ${true} | ${false}
${false} | ${true} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${true} | ${false} | ${false} | ${false}
${false} | ${true} | ${[]} | ${false} | ${true} | ${false} | ${false}
${true} | ${false} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${false} | ${false} | ${true} | ${true}
${true} | ${false} | ${[]} | ${false} | ${false} | ${true} | ${true}
${true} | ${true} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${false} | ${false} | ${false} | ${true}
${true} | ${true} | ${[]} | ${false} | ${false} | ${false} | ${true}
isLoading | graphqlFieldName | replicableItems | showReplicableItems | showEmptyState | showFilterBar | showLoader
${false} | ${null} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${true} | ${false} | ${true} | ${false}
${false} | ${null} | ${[]} | ${false} | ${true} | ${true} | ${false}
${false} | ${MOCK_GRAPHQL_REGISTRY} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${true} | ${false} | ${false} | ${false}
${false} | ${MOCK_GRAPHQL_REGISTRY} | ${[]} | ${false} | ${true} | ${false} | ${false}
${true} | ${null} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${false} | ${false} | ${true} | ${true}
${true} | ${null} | ${[]} | ${false} | ${false} | ${true} | ${true}
${true} | ${MOCK_GRAPHQL_REGISTRY} | ${MOCK_BASIC_FETCH_DATA_MAP} | ${false} | ${false} | ${false} | ${true}
${true} | ${MOCK_GRAPHQL_REGISTRY} | ${[]} | ${false} | ${false} | ${false} | ${true}
`(
`template`,
({
isLoading,
useGraphQl,
graphqlFieldName,
replicableItems,
showReplicableItems,
showEmptyState,
......@@ -74,15 +73,15 @@ describe('GeoReplicableApp', () => {
showLoader,
}) => {
beforeEach(() => {
createStore({ graphqlFieldName });
createComponent();
});
describe(`when isLoading is ${isLoading} and useGraphQl is ${useGraphQl}, ${
describe(`when isLoading is ${isLoading} and graphqlFieldName is ${graphqlFieldName}, ${
replicableItems.length ? 'with' : 'without'
} replicableItems`, () => {
beforeEach(() => {
wrapper.vm.$store.state.isLoading = isLoading;
wrapper.vm.$store.state.useGraphQl = useGraphQl;
wrapper.vm.$store.state.replicableItems = replicableItems;
wrapper.vm.$store.state.paginationData.total = replicableItems.length;
});
......@@ -108,11 +107,12 @@ describe('GeoReplicableApp', () => {
describe('onCreate', () => {
beforeEach(() => {
createStore();
createComponent();
});
it('calls fetchReplicableItems', () => {
expect(actionSpies.fetchReplicableItems).toHaveBeenCalled();
expect(store.dispatch).toHaveBeenCalledWith('fetchReplicableItems');
});
});
});
......@@ -23,7 +23,7 @@ describe('GeoReplicableEmptyState', () => {
const createComponent = () => {
wrapper = shallowMount(GeoReplicableEmptyState, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null }),
propsData,
});
};
......
......@@ -22,7 +22,7 @@ describe('GeoReplicableFilterBar', () => {
const createComponent = () => {
wrapper = mount(GeoReplicableFilterBar, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null }),
methods: {
...actionSpies,
},
......
......@@ -29,7 +29,7 @@ describe('GeoReplicableItem', () => {
const createComponent = (props = {}) => {
wrapper = mount(GeoReplicableItem, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null }),
propsData: {
...defaultProps,
...props,
......
......@@ -11,6 +11,7 @@ import {
MOCK_REPLICABLE_TYPE,
MOCK_GRAPHQL_PAGINATION_DATA,
MOCK_RESTFUL_PAGINATION_DATA,
MOCK_GRAPHQL_REGISTRY,
} from '../mock_data';
const localVue = createLocalVue();
......@@ -21,7 +22,7 @@ describe('GeoReplicable', () => {
let store;
const createStore = options => {
store = initStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false, ...options });
store = initStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null, ...options });
jest.spyOn(store, 'dispatch').mockImplementation();
};
......@@ -67,17 +68,17 @@ describe('GeoReplicable', () => {
});
});
describe('GlPagination', () => {
describe('when useGraphQl is false', () => {
describe('when graphqlFieldName is not defined', () => {
it('renders always', () => {
createStore({ useGraphQl: false });
createStore();
createComponent();
expect(findGlPagination().exists()).toBe(true);
});
});
describe('when useGraphQl is true', () => {
describe('when graphqlFieldName is defined', () => {
it('renders always', () => {
createStore({ useGraphQl: true });
createStore({ graphqlFieldName: MOCK_GRAPHQL_REGISTRY });
createComponent();
expect(findGlPagination().exists()).toBe(true);
});
......@@ -85,16 +86,16 @@ describe('GeoReplicable', () => {
});
describe.each`
useGraphQl | currentPage | newPage | action
${false} | ${1} | ${2} | ${undefined}
${false} | ${2} | ${1} | ${undefined}
${true} | ${1} | ${2} | ${'next'}
${true} | ${2} | ${1} | ${'prev'}
`(`changing the page`, ({ useGraphQl, currentPage, newPage, action }) => {
describe(`when useGraphQl is ${useGraphQl}`, () => {
graphqlFieldName | currentPage | newPage | action
${null} | ${1} | ${2} | ${undefined}
${null} | ${2} | ${1} | ${undefined}
${MOCK_GRAPHQL_REGISTRY} | ${1} | ${2} | ${'next'}
${MOCK_GRAPHQL_REGISTRY} | ${2} | ${1} | ${'prev'}
`(`changing the page`, ({ graphqlFieldName, currentPage, newPage, action }) => {
describe(`when graphqlFieldName is ${graphqlFieldName}`, () => {
describe(`from ${currentPage} to ${newPage}`, () => {
beforeEach(() => {
createStore({ useGraphQl });
createStore({ graphqlFieldName });
store.commit(types.RECEIVE_REPLICABLE_ITEMS_SUCCESS, {
data: MOCK_BASIC_FETCH_DATA_MAP,
pagination: { ...MOCK_GRAPHQL_PAGINATION_DATA, page: currentPage },
......
......@@ -24,7 +24,7 @@ describe('GeoReplicableStatus', () => {
const createComponent = () => {
wrapper = mount(GeoReplicableStatus, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null }),
propsData,
});
};
......
......@@ -20,7 +20,7 @@ describe('GeoReplicableTimeAgo', () => {
const createComponent = () => {
wrapper = mount(GeoReplicableTimeAgo, {
localVue,
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false }),
store: createStore({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null }),
propsData,
});
};
......
......@@ -7,6 +7,8 @@ export const MOCK_GEO_TROUBLESHOOTING_LINK =
export const MOCK_REPLICABLE_TYPE = 'designs';
export const MOCK_GRAPHQL_REGISTRY = 'designsRegistry';
export const MOCK_BASIC_FETCH_RESPONSE = {
data: [
{
......@@ -53,7 +55,6 @@ export const MOCK_BASIC_GRAPHQL_QUERY_RESPONSE = {
pageInfo: MOCK_GRAPHQL_PAGINATION_DATA,
edges: [
{
cursor: 'abc123',
node: {
id: 'git/1',
packageFileId: '1',
......@@ -62,7 +63,6 @@ export const MOCK_BASIC_GRAPHQL_QUERY_RESPONSE = {
},
},
{
cursor: 'abc124',
node: {
id: 'git/2',
packageFileId: '2',
......
......@@ -8,7 +8,7 @@ import * as types from 'ee/geo_replicable/store/mutation_types';
import createState from 'ee/geo_replicable/store/state';
import { ACTION_TYPES, PREV, NEXT, DEFAULT_PAGE_SIZE } from 'ee/geo_replicable/constants';
import { gqClient } from 'ee/geo_replicable/utils';
import packageFilesQuery from 'ee/geo_replicable/graphql/package_files.query.graphql';
import buildReplicableTypeQuery from 'ee/geo_replicable/graphql/replicable_type_query_builder';
import {
MOCK_BASIC_FETCH_DATA_MAP,
MOCK_BASIC_FETCH_RESPONSE,
......@@ -17,6 +17,7 @@ import {
MOCK_RESTFUL_PAGINATION_DATA,
MOCK_BASIC_GRAPHQL_QUERY_RESPONSE,
MOCK_GRAPHQL_PAGINATION_DATA,
MOCK_GRAPHQL_REGISTRY,
} from '../mock_data';
jest.mock('~/flash');
......@@ -26,7 +27,7 @@ describe('GeoReplicable Store Actions', () => {
let state;
beforeEach(() => {
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false });
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null });
});
describe('requestReplicableItems', () => {
......@@ -115,6 +116,10 @@ describe('GeoReplicable Store Actions', () => {
});
describe('fetchReplicableItemsGraphQl', () => {
beforeEach(() => {
state.graphqlFieldName = MOCK_GRAPHQL_REGISTRY;
});
describe('on success', () => {
beforeEach(() => {
jest.spyOn(gqClient, 'query').mockResolvedValue({
......@@ -143,7 +148,7 @@ describe('GeoReplicable Store Actions', () => {
],
() => {
expect(gqClient.query).toHaveBeenCalledWith({
query: packageFilesQuery,
query: buildReplicableTypeQuery(MOCK_GRAPHQL_REGISTRY),
variables: { before: '', after: '', first: DEFAULT_PAGE_SIZE, last: null },
});
},
......@@ -170,7 +175,7 @@ describe('GeoReplicable Store Actions', () => {
],
() => {
expect(gqClient.query).toHaveBeenCalledWith({
query: packageFilesQuery,
query: buildReplicableTypeQuery(MOCK_GRAPHQL_REGISTRY),
variables: {
before: '',
after: MOCK_GRAPHQL_PAGINATION_DATA.endCursor,
......@@ -202,7 +207,7 @@ describe('GeoReplicable Store Actions', () => {
],
() => {
expect(gqClient.query).toHaveBeenCalledWith({
query: packageFilesQuery,
query: buildReplicableTypeQuery(MOCK_GRAPHQL_REGISTRY),
variables: {
before: MOCK_GRAPHQL_PAGINATION_DATA.startCursor,
after: '',
......
......@@ -6,7 +6,7 @@ describe('GeoReplicable Store Getters', () => {
let state;
beforeEach(() => {
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false });
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null });
});
describe('replicableTypeName', () => {
......
......@@ -11,7 +11,7 @@ import {
describe('GeoReplicable Store Mutations', () => {
let state;
beforeEach(() => {
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, useGraphQl: false });
state = createState({ replicableType: MOCK_REPLICABLE_TYPE, graphqlFieldName: null });
});
describe('SET_FILTER', () => {
......
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