Commit f4414161 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch 'nfriend-remove-releases_pagination_rest-component' into 'master'

Remove releases_pagination_rest.vue component

See merge request gitlab-org/gitlab!61531
parents 08445672 1c9e97a7
<script> <script>
import ReleasesPaginationGraphql from './releases_pagination_graphql.vue'; import { GlKeysetPagination } from '@gitlab/ui';
import ReleasesPaginationRest from './releases_pagination_rest.vue'; import { mapActions, mapState } from 'vuex';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
export default { export default {
name: 'ReleasesPagination', name: 'ReleasesPaginationGraphql',
components: { ReleasesPaginationGraphql, ReleasesPaginationRest }, components: { GlKeysetPagination },
computed: { computed: {
// TODO: Remove the ReleasesPaginationRest component since ...mapState('index', ['pageInfo']),
// it is never shown. showPagination() {
// https://gitlab.com/gitlab-org/gitlab/-/issues/329267 return this.pageInfo.hasPreviousPage || this.pageInfo.hasNextPage;
useGraphQLEndpoint() { },
return true; },
methods: {
...mapActions('index', ['fetchReleases']),
onPrev(before) {
historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
this.fetchReleases({ before });
},
onNext(after) {
historyPushState(buildUrlWithCurrentLocation(`?after=${after}`));
this.fetchReleases({ after });
}, },
}, },
}; };
</script> </script>
<template> <template>
<div class="gl-display-flex gl-justify-content-center"> <div class="gl-display-flex gl-justify-content-center">
<releases-pagination-graphql v-if="useGraphQLEndpoint" /> <gl-keyset-pagination
<releases-pagination-rest v-else /> v-if="showPagination"
v-bind="pageInfo"
@prev="onPrev($event)"
@next="onNext($event)"
/>
</div> </div>
</template> </template>
<script>
import { GlKeysetPagination } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
export default {
name: 'ReleasesPaginationGraphql',
components: { GlKeysetPagination },
computed: {
...mapState('index', ['graphQlPageInfo']),
showPagination() {
return this.graphQlPageInfo.hasPreviousPage || this.graphQlPageInfo.hasNextPage;
},
},
methods: {
...mapActions('index', ['fetchReleases']),
onPrev(before) {
historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
this.fetchReleases({ before });
},
onNext(after) {
historyPushState(buildUrlWithCurrentLocation(`?after=${after}`));
this.fetchReleases({ after });
},
},
};
</script>
<template>
<gl-keyset-pagination
v-if="showPagination"
v-bind="graphQlPageInfo"
@prev="onPrev($event)"
@next="onNext($event)"
/>
</template>
<script>
import { mapActions, mapState } from 'vuex';
import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
export default {
name: 'ReleasesPaginationRest',
components: { TablePagination },
computed: {
...mapState('index', ['restPageInfo']),
},
methods: {
...mapActions('index', ['fetchReleases']),
onChangePage(page) {
historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
this.fetchReleases({ page });
},
},
};
</script>
<template>
<table-pagination :change="onChangePage" :page-info="restPageInfo" />
</template>
...@@ -45,11 +45,11 @@ export const fetchReleases = ({ dispatch, commit, state }, { before, after }) => ...@@ -45,11 +45,11 @@ export const fetchReleases = ({ dispatch, commit, state }, { before, after }) =>
}, },
}) })
.then((response) => { .then((response) => {
const { data, paginationInfo: graphQlPageInfo } = convertAllReleasesGraphQLResponse(response); const { data, paginationInfo: pageInfo } = convertAllReleasesGraphQLResponse(response);
commit(types.RECEIVE_RELEASES_SUCCESS, { commit(types.RECEIVE_RELEASES_SUCCESS, {
data, data,
graphQlPageInfo, pageInfo,
}); });
}) })
.catch(() => dispatch('receiveReleasesError')); .catch(() => dispatch('receiveReleasesError'));
......
...@@ -17,12 +17,11 @@ export default { ...@@ -17,12 +17,11 @@ export default {
* @param {Object} state * @param {Object} state
* @param {Object} resp * @param {Object} resp
*/ */
[types.RECEIVE_RELEASES_SUCCESS](state, { data, restPageInfo, graphQlPageInfo }) { [types.RECEIVE_RELEASES_SUCCESS](state, { data, pageInfo }) {
state.hasError = false; state.hasError = false;
state.isLoading = false; state.isLoading = false;
state.releases = data; state.releases = data;
state.restPageInfo = restPageInfo; state.pageInfo = pageInfo;
state.graphQlPageInfo = graphQlPageInfo;
}, },
/** /**
...@@ -36,8 +35,7 @@ export default { ...@@ -36,8 +35,7 @@ export default {
state.isLoading = false; state.isLoading = false;
state.releases = []; state.releases = [];
state.hasError = true; state.hasError = true;
state.restPageInfo = {}; state.pageInfo = {};
state.graphQlPageInfo = {};
}, },
[types.SET_SORTING](state, sorting) { [types.SET_SORTING](state, sorting) {
......
...@@ -16,8 +16,7 @@ export default ({ ...@@ -16,8 +16,7 @@ export default ({
isLoading: false, isLoading: false,
hasError: false, hasError: false,
releases: [], releases: [],
restPageInfo: {}, pageInfo: {},
graphQlPageInfo: {},
sorting: { sorting: {
sort: DESCENDING_ORDER, sort: DESCENDING_ORDER,
orderBy: RELEASED_AT, orderBy: RELEASED_AT,
......
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { historyPushState } from '~/lib/utils/common_utils';
import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
import createStore from '~/releases/stores';
import createIndexModule from '~/releases/stores/modules/index';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
historyPushState: jest.fn(),
}));
const localVue = createLocalVue();
localVue.use(Vuex);
describe('~/releases/components/releases_pagination_graphql.vue', () => {
let wrapper;
let indexModule;
const cursors = {
startCursor: 'startCursor',
endCursor: 'endCursor',
};
const projectPath = 'my/project';
const createComponent = (pageInfo) => {
indexModule = createIndexModule({ projectPath });
indexModule.state.graphQlPageInfo = pageInfo;
indexModule.actions.fetchReleases = jest.fn();
wrapper = mount(ReleasesPaginationGraphql, {
store: createStore({
modules: {
index: indexModule,
},
featureFlags: {},
}),
localVue,
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
const findPrevButton = () => wrapper.find('[data-testid="prevButton"]');
const findNextButton = () => wrapper.find('[data-testid="nextButton"]');
const expectDisabledPrev = () => {
expect(findPrevButton().attributes().disabled).toBe('disabled');
};
const expectEnabledPrev = () => {
expect(findPrevButton().attributes().disabled).toBe(undefined);
};
const expectDisabledNext = () => {
expect(findNextButton().attributes().disabled).toBe('disabled');
};
const expectEnabledNext = () => {
expect(findNextButton().attributes().disabled).toBe(undefined);
};
describe('when there is only one page of results', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: false,
hasNextPage: false,
});
});
it('does not render anything', () => {
expect(wrapper.html()).toBe('');
});
});
describe('when there is a next page, but not a previous page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: false,
hasNextPage: true,
});
});
it('renders a disabled "Prev" button', () => {
expectDisabledPrev();
});
it('renders an enabled "Next" button', () => {
expectEnabledNext();
});
});
describe('when there is a previous page, but not a next page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: false,
});
});
it('renders a enabled "Prev" button', () => {
expectEnabledPrev();
});
it('renders an disabled "Next" button', () => {
expectDisabledNext();
});
});
describe('when there is both a previous page and a next page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: true,
});
});
it('renders a enabled "Prev" button', () => {
expectEnabledPrev();
});
it('renders an enabled "Next" button', () => {
expectEnabledNext();
});
});
describe('button behavior', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: true,
...cursors,
});
});
describe('next button behavior', () => {
beforeEach(() => {
findNextButton().trigger('click');
});
it('calls fetchReleases with the correct after cursor', () => {
expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { after: cursors.endCursor }],
]);
});
it('calls historyPushState with the new URL', () => {
expect(historyPushState.mock.calls).toEqual([
[expect.stringContaining(`?after=${cursors.endCursor}`)],
]);
});
});
describe('previous button behavior', () => {
beforeEach(() => {
findPrevButton().trigger('click');
});
it('calls fetchReleases with the correct before cursor', () => {
expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { before: cursors.startCursor }],
]);
});
it('calls historyPushState with the new URL', () => {
expect(historyPushState.mock.calls).toEqual([
[expect.stringContaining(`?before=${cursors.startCursor}`)],
]);
});
});
});
});
import { GlPagination } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import * as commonUtils from '~/lib/utils/common_utils';
import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue';
import createStore from '~/releases/stores';
import createIndexModule from '~/releases/stores/modules/index';
commonUtils.historyPushState = jest.fn();
const localVue = createLocalVue();
localVue.use(Vuex);
describe('~/releases/components/releases_pagination_rest.vue', () => {
let wrapper;
let indexModule;
const projectId = 19;
const createComponent = (pageInfo) => {
indexModule = createIndexModule({ projectId });
indexModule.state.restPageInfo = pageInfo;
indexModule.actions.fetchReleases = jest.fn();
wrapper = mount(ReleasesPaginationRest, {
store: createStore({
modules: {
index: indexModule,
},
featureFlags: {},
}),
localVue,
});
};
const findGlPagination = () => wrapper.find(GlPagination);
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when a page number is clicked', () => {
const newPage = 2;
beforeEach(() => {
createComponent({
perPage: 20,
page: 1,
total: 40,
totalPages: 2,
nextPage: 2,
});
findGlPagination().vm.$emit('input', newPage);
});
it('calls fetchReleases with the correct page', () => {
expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { page: newPage }],
]);
});
it('calls historyPushState with the new URL', () => {
expect(commonUtils.historyPushState.mock.calls).toEqual([
[expect.stringContaining(`?page=${newPage}`)],
]);
});
});
});
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { GlKeysetPagination } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { historyPushState } from '~/lib/utils/common_utils';
import ReleasesPagination from '~/releases/components/releases_pagination.vue'; import ReleasesPagination from '~/releases/components/releases_pagination.vue';
import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue'; import createStore from '~/releases/stores';
import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue'; import createIndexModule from '~/releases/stores/modules/index';
jest.mock('~/lib/utils/common_utils', () => ({
...jest.requireActual('~/lib/utils/common_utils'),
historyPushState: jest.fn(),
}));
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
describe('~/releases/components/releases_pagination.vue', () => { describe('~/releases/components/releases_pagination.vue', () => {
let wrapper; let wrapper;
let indexModule;
const createComponent = (useGraphQLEndpoint) => { const cursors = {
const store = new Vuex.Store({ startCursor: 'startCursor',
getters: { endCursor: 'endCursor',
useGraphQLEndpoint: () => useGraphQLEndpoint,
},
});
wrapper = shallowMount(ReleasesPagination, { store, localVue });
}; };
beforeEach(() => { const projectPath = 'my/project';
createComponent(true);
}); const createComponent = (pageInfo) => {
indexModule = createIndexModule({ projectPath });
indexModule.state.pageInfo = pageInfo;
indexModule.actions.fetchReleases = jest.fn();
wrapper = mount(ReleasesPagination, {
store: createStore({
modules: {
index: indexModule,
},
featureFlags: {},
}),
localVue,
});
};
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
}); });
const findRestPagination = () => wrapper.find(ReleasesPaginationRest); const findGlKeysetPagination = () => wrapper.findComponent(GlKeysetPagination);
const findGraphQlPagination = () => wrapper.find(ReleasesPaginationGraphql); const findPrevButton = () => findGlKeysetPagination().find('[data-testid="prevButton"]');
const findNextButton = () => findGlKeysetPagination().find('[data-testid="nextButton"]');
const expectDisabledPrev = () => {
expect(findPrevButton().attributes().disabled).toBe('disabled');
};
const expectEnabledPrev = () => {
expect(findPrevButton().attributes().disabled).toBe(undefined);
};
const expectDisabledNext = () => {
expect(findNextButton().attributes().disabled).toBe('disabled');
};
const expectEnabledNext = () => {
expect(findNextButton().attributes().disabled).toBe(undefined);
};
describe('when there is only one page of results', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: false,
hasNextPage: false,
});
});
it('does not render a GlKeysetPagination', () => {
expect(findGlKeysetPagination().exists()).toBe(false);
});
});
describe('when there is a next page, but not a previous page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: false,
hasNextPage: true,
});
});
it('renders a disabled "Prev" button', () => {
expectDisabledPrev();
});
it('renders an enabled "Next" button', () => {
expectEnabledNext();
});
});
describe('when there is a previous page, but not a next page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: false,
});
});
it('renders a enabled "Prev" button', () => {
expectEnabledPrev();
});
it('renders an disabled "Next" button', () => {
expectDisabledNext();
});
});
describe('when there is both a previous page and a next page', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: true,
});
});
it('renders a enabled "Prev" button', () => {
expectEnabledPrev();
});
it('renders the GraphQL pagination component', () => { it('renders an enabled "Next" button', () => {
expect(findGraphQlPagination().exists()).toBe(true); expectEnabledNext();
expect(findRestPagination().exists()).toBe(false); });
});
describe('button behavior', () => {
beforeEach(() => {
createComponent({
hasPreviousPage: true,
hasNextPage: true,
...cursors,
});
});
describe('next button behavior', () => {
beforeEach(() => {
findNextButton().trigger('click');
});
it('calls fetchReleases with the correct after cursor', () => {
expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { after: cursors.endCursor }],
]);
});
it('calls historyPushState with the new URL', () => {
expect(historyPushState.mock.calls).toEqual([
[expect.stringContaining(`?after=${cursors.endCursor}`)],
]);
});
});
describe('previous button behavior', () => {
beforeEach(() => {
findPrevButton().trigger('click');
});
it('calls fetchReleases with the correct before cursor', () => {
expect(indexModule.actions.fetchReleases.mock.calls).toEqual([
[expect.anything(), { before: cursors.startCursor }],
]);
});
it('calls historyPushState with the new URL', () => {
expect(historyPushState.mock.calls).toEqual([
[expect.stringContaining(`?before=${cursors.startCursor}`)],
]);
});
});
}); });
}); });
...@@ -141,7 +141,7 @@ describe('Releases State actions', () => { ...@@ -141,7 +141,7 @@ describe('Releases State actions', () => {
type: types.RECEIVE_RELEASES_SUCCESS, type: types.RECEIVE_RELEASES_SUCCESS,
payload: { payload: {
data: convertedResponse.data, data: convertedResponse.data,
graphQlPageInfo: convertedResponse.paginationInfo, pageInfo: convertedResponse.paginationInfo,
}, },
}, },
], ],
......
import { getJSONFixture } from 'helpers/fixtures'; import { getJSONFixture } from 'helpers/fixtures';
import { parseIntPagination, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import * as types from '~/releases/stores/modules/index/mutation_types'; import * as types from '~/releases/stores/modules/index/mutation_types';
import mutations from '~/releases/stores/modules/index/mutations'; import mutations from '~/releases/stores/modules/index/mutations';
import createState from '~/releases/stores/modules/index/state'; import createState from '~/releases/stores/modules/index/state';
import { convertAllReleasesGraphQLResponse } from '~/releases/util'; import { convertAllReleasesGraphQLResponse } from '~/releases/util';
import { pageInfoHeadersWithoutPagination } from '../../../mock_data';
const originalRelease = getJSONFixture('api/releases/release.json'); const originalRelease = getJSONFixture('api/releases/release.json');
const originalReleases = [originalRelease]; const originalReleases = [originalRelease];
...@@ -15,14 +14,12 @@ const graphqlReleasesResponse = getJSONFixture( ...@@ -15,14 +14,12 @@ const graphqlReleasesResponse = getJSONFixture(
describe('Releases Store Mutations', () => { describe('Releases Store Mutations', () => {
let stateCopy; let stateCopy;
let restPageInfo; let pageInfo;
let graphQlPageInfo;
let releases; let releases;
beforeEach(() => { beforeEach(() => {
stateCopy = createState({}); stateCopy = createState({});
restPageInfo = parseIntPagination(pageInfoHeadersWithoutPagination); pageInfo = convertAllReleasesGraphQLResponse(graphqlReleasesResponse).paginationInfo;
graphQlPageInfo = convertAllReleasesGraphQLResponse(graphqlReleasesResponse).paginationInfo;
releases = convertObjectPropsToCamelCase(originalReleases, { deep: true }); releases = convertObjectPropsToCamelCase(originalReleases, { deep: true });
}); });
...@@ -37,8 +34,7 @@ describe('Releases Store Mutations', () => { ...@@ -37,8 +34,7 @@ describe('Releases Store Mutations', () => {
describe('RECEIVE_RELEASES_SUCCESS', () => { describe('RECEIVE_RELEASES_SUCCESS', () => {
beforeEach(() => { beforeEach(() => {
mutations[types.RECEIVE_RELEASES_SUCCESS](stateCopy, { mutations[types.RECEIVE_RELEASES_SUCCESS](stateCopy, {
restPageInfo, pageInfo,
graphQlPageInfo,
data: releases, data: releases,
}); });
}); });
...@@ -55,20 +51,15 @@ describe('Releases Store Mutations', () => { ...@@ -55,20 +51,15 @@ describe('Releases Store Mutations', () => {
expect(stateCopy.releases).toEqual(releases); expect(stateCopy.releases).toEqual(releases);
}); });
it('sets restPageInfo', () => { it('sets pageInfo', () => {
expect(stateCopy.restPageInfo).toEqual(restPageInfo); expect(stateCopy.pageInfo).toEqual(pageInfo);
});
it('sets graphQlPageInfo', () => {
expect(stateCopy.graphQlPageInfo).toEqual(graphQlPageInfo);
}); });
}); });
describe('RECEIVE_RELEASES_ERROR', () => { describe('RECEIVE_RELEASES_ERROR', () => {
it('resets data', () => { it('resets data', () => {
mutations[types.RECEIVE_RELEASES_SUCCESS](stateCopy, { mutations[types.RECEIVE_RELEASES_SUCCESS](stateCopy, {
restPageInfo, pageInfo,
graphQlPageInfo,
data: releases, data: releases,
}); });
...@@ -76,8 +67,7 @@ describe('Releases Store Mutations', () => { ...@@ -76,8 +67,7 @@ describe('Releases Store Mutations', () => {
expect(stateCopy.isLoading).toEqual(false); expect(stateCopy.isLoading).toEqual(false);
expect(stateCopy.releases).toEqual([]); expect(stateCopy.releases).toEqual([]);
expect(stateCopy.restPageInfo).toEqual({}); expect(stateCopy.pageInfo).toEqual({});
expect(stateCopy.graphQlPageInfo).toEqual({});
}); });
}); });
......
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