summaryrefslogtreecommitdiff
path: root/spec/frontend/incidents/components/incidents_list_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/incidents/components/incidents_list_spec.js')
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js211
1 files changed, 146 insertions, 65 deletions
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 307806e0a8a..1b98d488854 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -5,7 +5,6 @@ import {
GlTable,
GlAvatar,
GlPagination,
- GlSearchBoxByType,
GlTab,
GlTabs,
GlBadge,
@@ -15,13 +14,24 @@ import { visitUrl, joinPaths, mergeUrlParams } from '~/lib/utils/url_utility';
import IncidentsList from '~/incidents/components/incidents_list.vue';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { I18N, INCIDENT_STATUS_TABS } from '~/incidents/constants';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import {
+ I18N,
+ INCIDENT_STATUS_TABS,
+ TH_CREATED_AT_TEST_ID,
+ TH_SEVERITY_TEST_ID,
+ TH_PUBLISHED_TEST_ID,
+} from '~/incidents/constants';
import mockIncidents from '../mocks/incidents.json';
+import mockFilters from '../mocks/incidents_filter.json';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
- joinPaths: jest.fn().mockName('joinPaths'),
- mergeUrlParams: jest.fn().mockName('mergeUrlParams'),
+ joinPaths: jest.fn(),
+ mergeUrlParams: jest.fn(),
+ setUrlParams: jest.fn(),
+ updateHistory: jest.fn(),
}));
describe('Incidents List', () => {
@@ -41,9 +51,7 @@ describe('Incidents List', () => {
const findAlert = () => wrapper.find(GlAlert);
const findLoader = () => wrapper.find(GlLoadingIcon);
const findTimeAgo = () => wrapper.findAll(TimeAgoTooltip);
- const findDateColumnHeader = () =>
- wrapper.find('[data-testid="incident-management-created-at-sort"]');
- const findSearch = () => wrapper.find(GlSearchBoxByType);
+ const findSearch = () => wrapper.find(FilteredSearchBar);
const findAssingees = () => wrapper.findAll('[data-testid="incident-assignees"]');
const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]');
const findClosedIcon = () => wrapper.findAll("[data-testid='incident-closed']");
@@ -73,9 +81,13 @@ describe('Incidents List', () => {
newIssuePath,
incidentTemplateName,
incidentType,
- issuePath: '/project/isssues',
+ issuePath: '/project/issues',
publishedAvailable: true,
emptyListSvgPath,
+ textQuery: '',
+ authorUsernamesQuery: '',
+ assigneeUsernamesQuery: '',
+ issuesIncidentDetails: false,
},
stubs: {
GlButton: true,
@@ -171,13 +183,6 @@ describe('Incidents List', () => {
expect(src).toBe(avatarUrl);
});
- it('contains a link to the issue details', () => {
- findTableRows()
- .at(0)
- .trigger('click');
- expect(visitUrl).toHaveBeenCalledWith(joinPaths(`/project/isssues/`, mockIncidents[0].iid));
- });
-
it('renders a closed icon for closed incidents', () => {
expect(findClosedIcon().length).toBe(
mockIncidents.filter(({ state }) => state === 'closed').length,
@@ -188,6 +193,30 @@ describe('Incidents List', () => {
it('renders severity per row', () => {
expect(findSeverity().length).toBe(mockIncidents.length);
});
+
+ it('contains a link to the issue details page', () => {
+ findTableRows()
+ .at(0)
+ .trigger('click');
+ expect(visitUrl).toHaveBeenCalledWith(joinPaths(`/project/issues/`, mockIncidents[0].iid));
+ });
+
+ it('contains a link to the incident details page', async () => {
+ beforeEach(() =>
+ mountComponent({
+ data: { incidents: { list: mockIncidents }, incidentsCount: {} },
+ loading: false,
+ provide: { glFeatures: { issuesIncidentDetails: true } },
+ }),
+ );
+
+ findTableRows()
+ .at(0)
+ .trigger('click');
+ expect(visitUrl).toHaveBeenCalledWith(
+ joinPaths(`/project/issues/incident`, mockIncidents[0].iid),
+ );
+ });
});
describe('Create Incident', () => {
@@ -207,11 +236,10 @@ describe('Incidents List', () => {
);
});
- it('sets button loading on click', () => {
+ it('sets button loading on click', async () => {
findCreateIncidentBtn().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findCreateIncidentBtn().attributes('loading')).toBe('true');
- });
+ await wrapper.vm.$nextTick();
+ expect(findCreateIncidentBtn().attributes('loading')).toBe('true');
});
it("doesn't show the button when list is empty", () => {
@@ -243,51 +271,47 @@ describe('Incidents List', () => {
});
describe('prevPage', () => {
- it('returns prevPage button', () => {
+ it('returns prevPage button', async () => {
findPagination().vm.$emit('input', 3);
- return wrapper.vm.$nextTick(() => {
- expect(
- findPagination()
- .findAll('.page-item')
- .at(0)
- .text(),
- ).toBe('Prev');
- });
+ await wrapper.vm.$nextTick();
+ expect(
+ findPagination()
+ .findAll('.page-item')
+ .at(0)
+ .text(),
+ ).toBe('Prev');
});
- it('returns prevPage number', () => {
+ it('returns prevPage number', async () => {
findPagination().vm.$emit('input', 3);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.prevPage).toBe(2);
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.prevPage).toBe(2);
});
- it('returns 0 when it is the first page', () => {
+ it('returns 0 when it is the first page', async () => {
findPagination().vm.$emit('input', 1);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.prevPage).toBe(0);
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.prevPage).toBe(0);
});
});
describe('nextPage', () => {
- it('returns nextPage button', () => {
+ it('returns nextPage button', async () => {
findPagination().vm.$emit('input', 3);
- return wrapper.vm.$nextTick(() => {
- expect(
- findPagination()
- .findAll('.page-item')
- .at(1)
- .text(),
- ).toBe('Next');
- });
+ await wrapper.vm.$nextTick();
+ expect(
+ findPagination()
+ .findAll('.page-item')
+ .at(1)
+ .text(),
+ ).toBe('Next');
});
- it('returns nextPage number', () => {
+ it('returns nextPage number', async () => {
mountComponent({
data: {
incidents: {
@@ -301,21 +325,19 @@ describe('Incidents List', () => {
});
findPagination().vm.$emit('input', 1);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.nextPage).toBe(2);
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.nextPage).toBe(2);
});
- it('returns `null` when currentPage is already last page', () => {
+ it('returns `null` when currentPage is already last page', async () => {
findStatusTabs().vm.$emit('input', 1);
findPagination().vm.$emit('input', 1);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.nextPage).toBeNull();
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.nextPage).toBeNull();
});
});
- describe('Search', () => {
+ describe('Filtered search component', () => {
beforeEach(() => {
mountComponent({
data: {
@@ -331,15 +353,62 @@ describe('Incidents List', () => {
});
it('renders the search component for incidents', () => {
- expect(findSearch().exists()).toBe(true);
+ expect(findSearch().props('searchInputPlaceholder')).toBe('Search or filter results…');
+ expect(findSearch().props('tokens')).toEqual([
+ {
+ type: 'author_username',
+ icon: 'user',
+ title: 'Author',
+ unique: true,
+ symbol: '@',
+ token: AuthorToken,
+ operators: [{ value: '=', description: 'is', default: 'true' }],
+ fetchPath: '/project/path',
+ fetchAuthors: expect.any(Function),
+ },
+ {
+ type: 'assignee_username',
+ icon: 'user',
+ title: 'Assignees',
+ unique: true,
+ symbol: '@',
+ token: AuthorToken,
+ operators: [{ value: '=', description: 'is', default: 'true' }],
+ fetchPath: '/project/path',
+ fetchAuthors: expect.any(Function),
+ },
+ ]);
+ expect(findSearch().props('recentSearchesStorageKey')).toBe('incidents');
+ });
+
+ it('returns correctly applied filter search values', async () => {
+ const searchTerm = 'foo';
+ wrapper.setData({
+ searchTerm,
+ });
+
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.filteredSearchValue).toEqual([searchTerm]);
});
- it('sets the `searchTerm` graphql variable', () => {
- const SEARCH_TERM = 'Simple Incident';
+ it('updates props tied to getIncidents GraphQL query', () => {
+ wrapper.vm.handleFilterIncidents(mockFilters);
- findSearch().vm.$emit('input', SEARCH_TERM);
+ expect(wrapper.vm.authorUsername).toBe('root');
+ expect(wrapper.vm.assigneeUsernames).toEqual('root2');
+ expect(wrapper.vm.searchTerm).toBe(mockFilters[2].value.data);
+ });
- expect(wrapper.vm.$data.searchTerm).toBe(SEARCH_TERM);
+ it('updates props `searchTerm` and `authorUsername` with empty values when passed filters param is empty', () => {
+ wrapper.setData({
+ authorUsername: 'foo',
+ searchTerm: 'bar',
+ });
+
+ wrapper.vm.handleFilterIncidents([]);
+
+ expect(wrapper.vm.authorUsername).toBe('');
+ expect(wrapper.vm.searchTerm).toBe('');
});
});
@@ -383,13 +452,25 @@ describe('Incidents List', () => {
});
});
- it('updates sort with new direction and column key', () => {
- expect(findDateColumnHeader().attributes('aria-sort')).toBe('descending');
+ const descSort = 'descending';
+ const ascSort = 'ascending';
+ const noneSort = 'none';
- findDateColumnHeader().trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(findDateColumnHeader().attributes('aria-sort')).toBe('ascending');
- });
+ it.each`
+ selector | initialSort | firstSort | nextSort
+ ${TH_CREATED_AT_TEST_ID} | ${descSort} | ${ascSort} | ${descSort}
+ ${TH_SEVERITY_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
+ ${TH_PUBLISHED_TEST_ID} | ${noneSort} | ${descSort} | ${ascSort}
+ `('updates sort with new direction', async ({ selector, initialSort, firstSort, nextSort }) => {
+ const [[attr, value]] = Object.entries(selector);
+ const columnHeader = () => wrapper.find(`[${attr}="${value}"]`);
+ expect(columnHeader().attributes('aria-sort')).toBe(initialSort);
+ columnHeader().trigger('click');
+ await wrapper.vm.$nextTick();
+ expect(columnHeader().attributes('aria-sort')).toBe(firstSort);
+ columnHeader().trigger('click');
+ await wrapper.vm.$nextTick();
+ expect(columnHeader().attributes('aria-sort')).toBe(nextSort);
});
});
});