Commit 957906d2 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '213881-alerts-list-pagination' into 'master'

Alerts list pagination

See merge request gitlab-org/gitlab!33073
parents d9f8f1d2 56d8064a
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
GlTabs, GlTabs,
GlTab, GlTab,
GlBadge, GlBadge,
GlPagination,
} from '@gitlab/ui'; } from '@gitlab/ui';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
...@@ -22,6 +23,7 @@ import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query ...@@ -22,6 +23,7 @@ import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query
import { import {
ALERTS_STATUS_TABS, ALERTS_STATUS_TABS,
ALERTS_SEVERITY_LABELS, ALERTS_SEVERITY_LABELS,
DEFAULT_PAGE_SIZE,
trackAlertListViewsOptions, trackAlertListViewsOptions,
trackAlertStatusUpdateOptions, trackAlertStatusUpdateOptions,
} from '../constants'; } from '../constants';
...@@ -34,6 +36,14 @@ const bodyTrClass = ...@@ -34,6 +36,14 @@ const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200'; 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200';
const findDefaultSortColumn = () => document.querySelector('.js-started-at'); const findDefaultSortColumn = () => document.querySelector('.js-started-at');
const initialPaginationState = {
currentPage: 1,
prevPageCursor: '',
nextPageCursor: '',
firstPageSize: DEFAULT_PAGE_SIZE,
lastPageSize: null,
};
export default { export default {
i18n: { i18n: {
noAlertsMsg: s__( noAlertsMsg: s__(
...@@ -110,6 +120,7 @@ export default { ...@@ -110,6 +120,7 @@ export default {
GlTabs, GlTabs,
GlTab, GlTab,
GlBadge, GlBadge,
GlPagination,
}, },
props: { props: {
projectPath: { projectPath: {
...@@ -142,10 +153,20 @@ export default { ...@@ -142,10 +153,20 @@ export default {
projectPath: this.projectPath, projectPath: this.projectPath,
statuses: this.statusFilter, statuses: this.statusFilter,
sort: this.sort, sort: this.sort,
firstPageSize: this.pagination.firstPageSize,
lastPageSize: this.pagination.lastPageSize,
prevPageCursor: this.pagination.prevPageCursor,
nextPageCursor: this.pagination.nextPageCursor,
}; };
}, },
update(data) { update(data) {
return data.project?.alertManagementAlerts?.nodes; const { alertManagementAlerts: { nodes: list = [], pageInfo = {} } = {} } =
data.project || {};
return {
list,
pageInfo,
};
}, },
error() { error() {
this.errored = true; this.errored = true;
...@@ -169,7 +190,9 @@ export default { ...@@ -169,7 +190,9 @@ export default {
isAlertDismissed: false, isAlertDismissed: false,
isErrorAlertDismissed: false, isErrorAlertDismissed: false,
sort: 'STARTED_AT_ASC', sort: 'STARTED_AT_ASC',
statusFilter: this.$options.statusTabs[4].filters, statusFilter: [],
filteredByStatus: '',
pagination: initialPaginationState,
}; };
}, },
computed: { computed: {
...@@ -185,19 +208,34 @@ export default { ...@@ -185,19 +208,34 @@ export default {
return this.$apollo.queries.alerts.loading; return this.$apollo.queries.alerts.loading;
}, },
hasAlerts() { hasAlerts() {
return this.alerts?.length; return this.alerts?.list?.length;
}, },
tbodyTrClass() { tbodyTrClass() {
return !this.loading && this.hasAlerts ? bodyTrClass : ''; return !this.loading && this.hasAlerts ? bodyTrClass : '';
}, },
showPaginationControls() {
return Boolean(this.prevPage || this.nextPage);
},
alertsForCurrentTab() {
return this.alertsCount ? this.alertsCount[this.filteredByStatus.toLowerCase()] : 0;
},
prevPage() {
return Math.max(this.pagination.currentPage - 1, 0);
},
nextPage() {
const nextPage = this.pagination.currentPage + 1;
return nextPage > Math.ceil(this.alertsForCurrentTab / DEFAULT_PAGE_SIZE) ? null : nextPage;
},
}, },
mounted() { mounted() {
findDefaultSortColumn().ariaSort = 'ascending';
this.trackPageViews(); this.trackPageViews();
}, },
methods: { methods: {
filterAlertsByStatus(tabIndex) { filterAlertsByStatus(tabIndex) {
this.statusFilter = this.$options.statusTabs[tabIndex].filters; this.resetPagination();
const { filters, status } = this.$options.statusTabs[tabIndex];
this.statusFilter = filters;
this.filteredByStatus = status;
}, },
fetchSortedData({ sortBy, sortDesc }) { fetchSortedData({ sortBy, sortDesc }) {
const sortDirection = sortDesc ? 'DESC' : 'ASC'; const sortDirection = sortDesc ? 'DESC' : 'ASC';
...@@ -206,6 +244,7 @@ export default { ...@@ -206,6 +244,7 @@ export default {
if (sortBy !== 'startedAt') { if (sortBy !== 'startedAt') {
findDefaultSortColumn().ariaSort = 'none'; findDefaultSortColumn().ariaSort = 'none';
} }
this.resetPagination();
this.sort = `${sortColumn}_${sortDirection}`; this.sort = `${sortColumn}_${sortDirection}`;
}, },
updateAlertStatus(status, iid) { updateAlertStatus(status, iid) {
...@@ -222,6 +261,7 @@ export default { ...@@ -222,6 +261,7 @@ export default {
this.trackStatusUpdate(status); this.trackStatusUpdate(status);
this.$apollo.queries.alerts.refetch(); this.$apollo.queries.alerts.refetch();
this.$apollo.queries.alertsCount.refetch(); this.$apollo.queries.alertsCount.refetch();
this.resetPagination();
}) })
.catch(() => { .catch(() => {
createFlash( createFlash(
...@@ -246,6 +286,28 @@ export default { ...@@ -246,6 +286,28 @@ export default {
// TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405 // TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405
return assignees?.length > 0 ? assignees[0]?.username : s__('AlertManagement|Unassigned'); return assignees?.length > 0 ? assignees[0]?.username : s__('AlertManagement|Unassigned');
}, },
handlePageChange(page) {
const { startCursor, endCursor } = this.alerts.pageInfo;
if (page > this.pagination.currentPage) {
this.pagination = {
...initialPaginationState,
nextPageCursor: endCursor,
currentPage: page,
};
} else {
this.pagination = {
lastPageSize: DEFAULT_PAGE_SIZE,
firstPageSize: null,
prevPageCursor: startCursor,
nextPageCursor: '',
currentPage: page,
};
}
},
resetPagination() {
this.pagination = initialPaginationState;
},
}, },
}; };
</script> </script>
...@@ -275,7 +337,7 @@ export default { ...@@ -275,7 +337,7 @@ export default {
</h4> </h4>
<gl-table <gl-table
class="alert-management-table mt-3" class="alert-management-table mt-3"
:items="alerts" :items="alerts ? alerts.list : []"
:fields="$options.fields" :fields="$options.fields"
:show-empty="true" :show-empty="true"
:busy="loading" :busy="loading"
...@@ -283,6 +345,7 @@ export default { ...@@ -283,6 +345,7 @@ export default {
:tbody-tr-class="tbodyTrClass" :tbody-tr-class="tbodyTrClass"
:no-local-sorting="true" :no-local-sorting="true"
sort-icon-left sort-icon-left
sort-by="startedAt"
@row-clicked="navigateToAlertDetails" @row-clicked="navigateToAlertDetails"
@sort-changed="fetchSortedData" @sort-changed="fetchSortedData"
> >
...@@ -350,6 +413,16 @@ export default { ...@@ -350,6 +413,16 @@ export default {
<gl-loading-icon size="lg" color="dark" class="mt-3" /> <gl-loading-icon size="lg" color="dark" class="mt-3" />
</template> </template>
</gl-table> </gl-table>
<gl-pagination
v-if="showPaginationControls"
:value="pagination.currentPage"
:prev-page="prevPage"
:next-page="nextPage"
align="center"
class="gl-pagination prepend-top-default"
@input="handlePageChange"
/>
</div> </div>
<gl-empty-state <gl-empty-state
v-else v-else
......
...@@ -63,3 +63,5 @@ export const trackAlertStatusUpdateOptions = { ...@@ -63,3 +63,5 @@ export const trackAlertStatusUpdateOptions = {
action: 'update_alert_status', action: 'update_alert_status',
label: 'Status', label: 'Status',
}; };
export const DEFAULT_PAGE_SIZE = 10;
#import "../fragments/list_item.fragment.graphql" #import "../fragments/list_item.fragment.graphql"
query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!], $sort: AlertManagementAlertSort ) { query getAlerts(
project(fullPath: $projectPath) { $projectPath: ID!,
alertManagementAlerts(statuses: $statuses, sort: $sort) { $statuses: [AlertManagementStatus!],
nodes { $sort: AlertManagementAlertSort,
...AlertListItem $firstPageSize: Int,
} $lastPageSize: Int,
$prevPageCursor: String = ""
$nextPageCursor: String = ""
) {
project(fullPath: $projectPath, ) {
alertManagementAlerts(
statuses: $statuses,
sort: $sort,
first: $firstPageSize
last: $lastPageSize,
after: $nextPageCursor,
before: $prevPageCursor
) {
nodes {
...AlertListItem
},
pageInfo {
hasNextPage
endCursor
hasPreviousPage
startCursor
}
}
} }
}
} }
---
title: Alerts list pagination
merge_request: 33073
author:
type: added
...@@ -7,8 +7,10 @@ import { ...@@ -7,8 +7,10 @@ import {
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
GlIcon, GlIcon,
GlTabs,
GlTab, GlTab,
GlBadge, GlBadge,
GlPagination,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
...@@ -39,19 +41,21 @@ describe('AlertManagementList', () => { ...@@ -39,19 +41,21 @@ describe('AlertManagementList', () => {
const findLoader = () => wrapper.find(GlLoadingIcon); const findLoader = () => wrapper.find(GlLoadingIcon);
const findStatusDropdown = () => wrapper.find(GlDropdown); const findStatusDropdown = () => wrapper.find(GlDropdown);
const findStatusFilterTabs = () => wrapper.findAll(GlTab); const findStatusFilterTabs = () => wrapper.findAll(GlTab);
const findStatusTabs = () => wrapper.find(GlTabs);
const findStatusFilterBadge = () => wrapper.findAll(GlBadge); const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
const findDateFields = () => wrapper.findAll(TimeAgo); const findDateFields = () => wrapper.findAll(TimeAgo);
const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem); const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]'); const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]'); const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
const findSeverityColumnHeader = () => wrapper.findAll('th').at(0); const findSeverityColumnHeader = () => wrapper.findAll('th').at(0);
const findStartTimeColumnHeader = () => wrapper.findAll('th').at(1);
const findPagination = () => wrapper.find(GlPagination);
const alertsCount = { const alertsCount = {
acknowledged: 6,
all: 16,
open: 14, open: 14,
resolved: 2,
triggered: 10, triggered: 10,
acknowledged: 6,
resolved: 1,
all: 16,
}; };
function mountComponent({ function mountComponent({
...@@ -76,6 +80,7 @@ describe('AlertManagementList', () => { ...@@ -76,6 +80,7 @@ describe('AlertManagementList', () => {
mocks: { mocks: {
$apollo: { $apollo: {
mutate: jest.fn(), mutate: jest.fn(),
query: jest.fn(),
queries: { queries: {
alerts: { alerts: {
loading, loading,
...@@ -134,7 +139,7 @@ describe('AlertManagementList', () => { ...@@ -134,7 +139,7 @@ describe('AlertManagementList', () => {
it('loading state', () => { it('loading state', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: null, alertsCount: null }, data: { alerts: {}, alertsCount: null },
loading: true, loading: true,
}); });
expect(findAlertsTable().exists()).toBe(true); expect(findAlertsTable().exists()).toBe(true);
...@@ -149,7 +154,7 @@ describe('AlertManagementList', () => { ...@@ -149,7 +154,7 @@ describe('AlertManagementList', () => {
it('error state', () => { it('error state', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: null, alertsCount: null, errored: true }, data: { alerts: { errors: ['error'] }, alertsCount: null, errored: true },
loading: false, loading: false,
}); });
expect(findAlertsTable().exists()).toBe(true); expect(findAlertsTable().exists()).toBe(true);
...@@ -166,7 +171,7 @@ describe('AlertManagementList', () => { ...@@ -166,7 +171,7 @@ describe('AlertManagementList', () => {
it('empty state', () => { it('empty state', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: [], alertsCount: { all: 0 }, errored: false }, data: { alerts: { list: [], pageInfo: {} }, alertsCount: { all: 0 }, errored: false },
loading: false, loading: false,
}); });
expect(findAlertsTable().exists()).toBe(true); expect(findAlertsTable().exists()).toBe(true);
...@@ -183,7 +188,7 @@ describe('AlertManagementList', () => { ...@@ -183,7 +188,7 @@ describe('AlertManagementList', () => {
it('has data state', () => { it('has data state', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
expect(findLoader().exists()).toBe(false); expect(findLoader().exists()).toBe(false);
...@@ -199,7 +204,7 @@ describe('AlertManagementList', () => { ...@@ -199,7 +204,7 @@ describe('AlertManagementList', () => {
it('displays status dropdown', () => { it('displays status dropdown', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
expect(findStatusDropdown().exists()).toBe(true); expect(findStatusDropdown().exists()).toBe(true);
...@@ -208,7 +213,7 @@ describe('AlertManagementList', () => { ...@@ -208,7 +213,7 @@ describe('AlertManagementList', () => {
it('shows correct severity icons', () => { it('shows correct severity icons', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
...@@ -225,7 +230,7 @@ describe('AlertManagementList', () => { ...@@ -225,7 +230,7 @@ describe('AlertManagementList', () => {
it('renders severity text', () => { it('renders severity text', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
...@@ -239,7 +244,7 @@ describe('AlertManagementList', () => { ...@@ -239,7 +244,7 @@ describe('AlertManagementList', () => {
it('renders Unassigned when no assignee(s) present', () => { it('renders Unassigned when no assignee(s) present', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
...@@ -253,7 +258,7 @@ describe('AlertManagementList', () => { ...@@ -253,7 +258,7 @@ describe('AlertManagementList', () => {
it('renders username(s) when assignee(s) present', () => { it('renders username(s) when assignee(s) present', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
...@@ -267,7 +272,7 @@ describe('AlertManagementList', () => { ...@@ -267,7 +272,7 @@ describe('AlertManagementList', () => {
it('navigates to the detail page when alert row is clicked', () => { it('navigates to the detail page when alert row is clicked', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
...@@ -282,15 +287,17 @@ describe('AlertManagementList', () => { ...@@ -282,15 +287,17 @@ describe('AlertManagementList', () => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { data: {
alerts: [ alerts: {
{ list: [
iid: 1, {
status: 'acknowledged', iid: 1,
startedAt: '2020-03-17T23:18:14.996Z', status: 'acknowledged',
endedAt: '2020-04-17T23:18:14.996Z', startedAt: '2020-03-17T23:18:14.996Z',
severity: 'high', endedAt: '2020-04-17T23:18:14.996Z',
}, severity: 'high',
], },
],
},
alertsCount, alertsCount,
errored: false, errored: false,
}, },
...@@ -326,27 +333,31 @@ describe('AlertManagementList', () => { ...@@ -326,27 +333,31 @@ describe('AlertManagementList', () => {
beforeEach(() => { beforeEach(() => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, errored: false, sort: 'STARTED_AT_ASC', alertsCount }, data: { alerts: { list: mockAlerts }, errored: false, sort: 'STARTED_AT_ASC', alertsCount },
loading: false, loading: false,
stubs: { GlTable },
}); });
}); });
it('updates sort with new direction and column key', () => { it('updates sort with new direction and column key', () => {
findSeverityColumnHeader().trigger('click'); findSeverityColumnHeader().trigger('click');
expect(wrapper.vm.$data.sort).toEqual('SEVERITY_ASC'); expect(wrapper.vm.$data.sort).toBe('SEVERITY_ASC');
findSeverityColumnHeader().trigger('click'); findSeverityColumnHeader().trigger('click');
expect(wrapper.vm.$data.sort).toEqual('SEVERITY_DESC'); expect(wrapper.vm.$data.sort).toBe('SEVERITY_DESC');
}); });
it('updates the `ariaSort` attribute so the sort icon appears in the proper column', () => { it('updates the `ariaSort` attribute so the sort icon appears in the proper column', () => {
expect(mockStartedAtCol.ariaSort).toEqual('ascending'); expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('ascending');
findSeverityColumnHeader().trigger('click'); findSeverityColumnHeader().trigger('click');
expect(mockStartedAtCol.ariaSort).toEqual('none'); wrapper.vm.$nextTick(() => {
expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('none');
expect(findSeverityColumnHeader().attributes('aria-sort')).toBe('ascending');
});
}); });
}); });
...@@ -367,7 +378,7 @@ describe('AlertManagementList', () => { ...@@ -367,7 +378,7 @@ describe('AlertManagementList', () => {
beforeEach(() => { beforeEach(() => {
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount, errored: false }, data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false, loading: false,
}); });
}); });
...@@ -403,7 +414,7 @@ describe('AlertManagementList', () => { ...@@ -403,7 +414,7 @@ describe('AlertManagementList', () => {
jest.spyOn(Tracking, 'event'); jest.spyOn(Tracking, 'event');
mountComponent({ mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true }, props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, alertsCount }, data: { alerts: { list: mockAlerts }, alertsCount },
loading: false, loading: false,
}); });
}); });
...@@ -424,4 +435,64 @@ describe('AlertManagementList', () => { ...@@ -424,4 +435,64 @@ describe('AlertManagementList', () => {
}); });
}); });
}); });
describe('Pagination', () => {
beforeEach(() => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: { list: mockAlerts, pageInfo: {} }, alertsCount, errored: false },
loading: false,
});
});
it('does NOT show pagination control when list is smaller than default page size', () => {
findStatusTabs().vm.$emit('input', 3);
wrapper.vm.$nextTick(() => {
expect(findPagination().exists()).toBe(false);
});
});
it('shows pagination control when list is larger than default page size', () => {
findStatusTabs().vm.$emit('input', 0);
wrapper.vm.$nextTick(() => {
expect(findPagination().exists()).toBe(true);
});
});
describe('prevPage', () => {
it('returns prevPage number', () => {
findPagination().vm.$emit('input', 3);
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.prevPage).toBe(2);
});
});
it('returns 0 when it is the first page', () => {
findPagination().vm.$emit('input', 1);
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.prevPage).toBe(0);
});
});
});
describe('nextPage', () => {
it('returns nextPage number', () => {
findPagination().vm.$emit('input', 1);
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.nextPage).toBe(2);
});
});
it('returns `null` when currentPage is already last page', () => {
findStatusTabs().vm.$emit('input', 3);
findPagination().vm.$emit('input', 1);
return wrapper.vm.$nextTick(() => {
expect(wrapper.vm.nextPage).toBeNull();
});
});
});
});
}); });
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