summaryrefslogtreecommitdiff
path: root/spec/frontend/issues_list
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/issues_list')
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js4
-rw-r--r--spec/frontend/issues_list/components/issues_list_app_spec.js74
-rw-r--r--spec/frontend/issues_list/mock_data.js77
-rw-r--r--spec/frontend/issues_list/utils_spec.js29
4 files changed, 113 insertions, 71 deletions
diff --git a/spec/frontend/issues_list/components/issuables_list_app_spec.js b/spec/frontend/issues_list/components/issuables_list_app_spec.js
index a7f3dd81517..86112dad444 100644
--- a/spec/frontend/issues_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -8,7 +8,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import Issuable from '~/issues_list/components/issuable.vue';
import IssuablesListApp from '~/issues_list/components/issuables_list_app.vue';
import { PAGE_SIZE, PAGE_SIZE_MANUAL, RELATIVE_POSITION } from '~/issues_list/constants';
@@ -104,7 +104,7 @@ describe('Issuables list component', () => {
});
it('flashes an error', () => {
- expect(flash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/issues_list/components/issues_list_app_spec.js b/spec/frontend/issues_list/components/issues_list_app_spec.js
index a3ac57ee1bb..846236e1fb5 100644
--- a/spec/frontend/issues_list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issues_list_app_spec.js
@@ -5,6 +5,7 @@ import { cloneDeep } from 'lodash';
import { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
+import getIssuesCountQuery from 'ee_else_ce/issues_list/queries/get_issues_count.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
@@ -13,15 +14,16 @@ import {
filteredTokens,
locationSearch,
urlParams,
+ getIssuesCountQueryResponse,
} from 'jest/issues_list/mock_data';
import createFlash from '~/flash';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
import {
- apiSortParams,
CREATED_DESC,
DUE_DATE_OVERDUE,
PARAM_DUE_DATE,
@@ -55,19 +57,18 @@ describe('IssuesListApp component', () => {
localVue.use(VueApollo);
const defaultProvide = {
- autocompleteUsersPath: 'autocomplete/users/path',
calendarPath: 'calendar/path',
canBulkUpdate: false,
emptyStateSvgPath: 'empty-state.svg',
exportCsvPath: 'export/csv/path',
hasBlockedIssuesFeature: true,
hasIssueWeightsFeature: true,
+ hasIterationsFeature: true,
hasProjectIssues: true,
- isSignedIn: false,
+ isSignedIn: true,
issuesPath: 'path/to/issues',
jiraIntegrationPath: 'jira/integration/path',
newIssuePath: 'new/issue/path',
- projectLabelsPath: 'project/labels/path',
projectPath: 'path/to/project',
rssPath: 'rss/path',
showNewIssueLink: true,
@@ -77,7 +78,7 @@ describe('IssuesListApp component', () => {
let defaultQueryResponse = getIssuesQueryResponse;
if (IS_EE) {
defaultQueryResponse = cloneDeep(getIssuesQueryResponse);
- defaultQueryResponse.data.project.issues.nodes[0].blockedByCount = 1;
+ defaultQueryResponse.data.project.issues.nodes[0].blockingCount = 1;
defaultQueryResponse.data.project.issues.nodes[0].healthStatus = null;
defaultQueryResponse.data.project.issues.nodes[0].weight = 5;
}
@@ -93,10 +94,14 @@ describe('IssuesListApp component', () => {
const mountComponent = ({
provide = {},
- response = defaultQueryResponse,
+ issuesQueryResponse = jest.fn().mockResolvedValue(defaultQueryResponse),
+ issuesQueryCountResponse = jest.fn().mockResolvedValue(getIssuesCountQueryResponse),
mountFn = shallowMount,
} = {}) => {
- const requestHandlers = [[getIssuesQuery, jest.fn().mockResolvedValue(response)]];
+ const requestHandlers = [
+ [getIssuesQuery, issuesQueryResponse],
+ [getIssuesCountQuery, issuesQueryCountResponse],
+ ];
const apolloProvider = createMockApollo(requestHandlers);
return mountFn(IssuesListApp, {
@@ -137,8 +142,8 @@ describe('IssuesListApp component', () => {
currentTab: IssuableStates.Opened,
tabCounts: {
opened: 1,
- closed: undefined,
- all: undefined,
+ closed: 1,
+ all: 1,
},
issuablesLoading: false,
isManualOrdering: false,
@@ -148,8 +153,8 @@ describe('IssuesListApp component', () => {
hasPreviousPage: getIssuesQueryResponse.data.project.issues.pageInfo.hasPreviousPage,
hasNextPage: getIssuesQueryResponse.data.project.issues.pageInfo.hasNextPage,
urlParams: {
+ sort: urlSortParams[CREATED_DESC],
state: IssuableStates.Opened,
- ...urlSortParams[CREATED_DESC],
},
});
});
@@ -178,7 +183,7 @@ describe('IssuesListApp component', () => {
describe('csv import/export component', () => {
describe('when user is signed in', () => {
- const search = '?search=refactor&state=opened&sort=created_date';
+ const search = '?search=refactor&sort=created_date&state=opened';
beforeEach(() => {
global.jsdom.reconfigure({ url: `${TEST_HOST}${search}` });
@@ -273,13 +278,17 @@ describe('IssuesListApp component', () => {
describe('sort', () => {
it.each(Object.keys(urlSortParams))('is set as %s from the url params', (sortKey) => {
- global.jsdom.reconfigure({ url: setUrlParams(urlSortParams[sortKey], TEST_HOST) });
+ global.jsdom.reconfigure({
+ url: setUrlParams({ sort: urlSortParams[sortKey] }, TEST_HOST),
+ });
wrapper = mountComponent();
expect(findIssuableList().props()).toMatchObject({
initialSortBy: sortKey,
- urlParams: urlSortParams[sortKey],
+ urlParams: {
+ sort: urlSortParams[sortKey],
+ },
});
});
});
@@ -542,9 +551,13 @@ describe('IssuesListApp component', () => {
});
it('renders all tokens', () => {
+ const preloadedAuthors = [
+ { ...mockCurrentUser, id: convertToGraphQLId('User', mockCurrentUser.id) },
+ ];
+
expect(findIssuableList().props('searchTokens')).toMatchObject([
- { type: TOKEN_TYPE_AUTHOR, preloadedAuthors: [mockCurrentUser] },
- { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors: [mockCurrentUser] },
+ { type: TOKEN_TYPE_AUTHOR, preloadedAuthors },
+ { type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors },
{ type: TOKEN_TYPE_MILESTONE },
{ type: TOKEN_TYPE_LABEL },
{ type: TOKEN_TYPE_MY_REACTION },
@@ -557,6 +570,29 @@ describe('IssuesListApp component', () => {
});
});
+ describe('errors', () => {
+ describe.each`
+ error | mountOption | message
+ ${'fetching issues'} | ${'issuesQueryResponse'} | ${IssuesListApp.i18n.errorFetchingIssues}
+ ${'fetching issue counts'} | ${'issuesQueryCountResponse'} | ${IssuesListApp.i18n.errorFetchingCounts}
+ `('when there is an error $error', ({ mountOption, message }) => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ [mountOption]: jest.fn().mockRejectedValue(new Error('ERROR')),
+ });
+ jest.runOnlyPendingTimers();
+ });
+
+ it('shows an error message', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ captureError: true,
+ error: new Error('Network error: ERROR'),
+ message,
+ });
+ });
+ });
+ });
+
describe('events', () => {
describe('when "click-tab" event is emitted by IssuableList', () => {
beforeEach(() => {
@@ -622,7 +658,7 @@ describe('IssuesListApp component', () => {
};
beforeEach(() => {
- wrapper = mountComponent({ response });
+ wrapper = mountComponent({ issuesQueryResponse: jest.fn().mockResolvedValue(response) });
jest.runOnlyPendingTimers();
});
@@ -640,7 +676,7 @@ describe('IssuesListApp component', () => {
});
describe('when "sort" event is emitted by IssuableList', () => {
- it.each(Object.keys(apiSortParams))(
+ it.each(Object.keys(urlSortParams))(
'updates to the new sort when payload is `%s`',
async (sortKey) => {
wrapper = mountComponent();
@@ -650,7 +686,9 @@ describe('IssuesListApp component', () => {
jest.runOnlyPendingTimers();
await nextTick();
- expect(findIssuableList().props('urlParams')).toMatchObject(urlSortParams[sortKey]);
+ expect(findIssuableList().props('urlParams')).toMatchObject({
+ sort: urlSortParams[sortKey],
+ });
},
);
});
diff --git a/spec/frontend/issues_list/mock_data.js b/spec/frontend/issues_list/mock_data.js
index 6c669e02070..fd59241fd1d 100644
--- a/spec/frontend/issues_list/mock_data.js
+++ b/spec/frontend/issues_list/mock_data.js
@@ -7,9 +7,8 @@ export const getIssuesQueryResponse = {
data: {
project: {
issues: {
- count: 1,
pageInfo: {
- hasNextPage: false,
+ hasNextPage: true,
hasPreviousPage: false,
startCursor: 'startcursor',
endCursor: 'endcursor',
@@ -70,6 +69,16 @@ export const getIssuesQueryResponse = {
},
};
+export const getIssuesCountQueryResponse = {
+ data: {
+ project: {
+ issues: {
+ count: 1,
+ },
+ },
+ },
+};
+
export const locationSearch = [
'?search=find+issues',
'author_username=homer',
@@ -86,10 +95,10 @@ export const locationSearch = [
'not[label_name][]=drama',
'my_reaction_emoji=thumbsup',
'confidential=no',
- 'iteration_title=season:+%234',
- 'not[iteration_title]=season:+%2320',
- 'epic_id=gitlab-org%3A%3A%2612',
- 'not[epic_id]=gitlab-org%3A%3A%2634',
+ 'iteration_id=4',
+ 'not[iteration_id]=20',
+ 'epic_id=12',
+ 'not[epic_id]=34',
'weight=1',
'not[weight]=3',
].join('&');
@@ -118,10 +127,10 @@ export const filteredTokens = [
{ type: 'labels', value: { data: 'drama', operator: OPERATOR_IS_NOT } },
{ type: 'my_reaction_emoji', value: { data: 'thumbsup', operator: OPERATOR_IS } },
{ type: 'confidential', value: { data: 'no', operator: OPERATOR_IS } },
- { type: 'iteration', value: { data: 'season: #4', operator: OPERATOR_IS } },
- { type: 'iteration', value: { data: 'season: #20', operator: OPERATOR_IS_NOT } },
- { type: 'epic_id', value: { data: 'gitlab-org::&12', operator: OPERATOR_IS } },
- { type: 'epic_id', value: { data: 'gitlab-org::&34', operator: OPERATOR_IS_NOT } },
+ { type: 'iteration', value: { data: '4', operator: OPERATOR_IS } },
+ { type: 'iteration', value: { data: '20', operator: OPERATOR_IS_NOT } },
+ { type: 'epic_id', value: { data: '12', operator: OPERATOR_IS } },
+ { type: 'epic_id', value: { data: '34', operator: OPERATOR_IS_NOT } },
{ type: 'weight', value: { data: '1', operator: OPERATOR_IS } },
{ type: 'weight', value: { data: '3', operator: OPERATOR_IS_NOT } },
{ type: 'filtered-search-term', value: { data: 'find' } },
@@ -138,30 +147,32 @@ export const filteredTokensWithSpecialValues = [
];
export const apiParams = {
- author_username: 'homer',
- 'not[author_username]': 'marge',
- assignee_username: ['bart', 'lisa'],
- 'not[assignee_username]': ['patty', 'selma'],
- milestone: 'season 4',
- 'not[milestone]': 'season 20',
- labels: ['cartoon', 'tv'],
- 'not[labels]': ['live action', 'drama'],
- my_reaction_emoji: 'thumbsup',
+ authorUsername: 'homer',
+ assigneeUsernames: ['bart', 'lisa'],
+ milestoneTitle: 'season 4',
+ labelName: ['cartoon', 'tv'],
+ myReactionEmoji: 'thumbsup',
confidential: 'no',
- iteration_title: 'season: #4',
- 'not[iteration_title]': 'season: #20',
- epic_id: '12',
- 'not[epic_id]': 'gitlab-org::&34',
+ iterationId: '4',
+ epicId: '12',
weight: '1',
- 'not[weight]': '3',
+ not: {
+ authorUsername: 'marge',
+ assigneeUsernames: ['patty', 'selma'],
+ milestoneTitle: 'season 20',
+ labelName: ['live action', 'drama'],
+ iterationId: '20',
+ epicId: '34',
+ weight: '3',
+ },
};
export const apiParamsWithSpecialValues = {
- assignee_id: '123',
- assignee_username: 'bart',
- my_reaction_emoji: 'None',
- iteration_id: 'Current',
- epic_id: 'None',
+ assigneeId: '123',
+ assigneeUsernames: 'bart',
+ myReactionEmoji: 'None',
+ iterationWildcardId: 'CURRENT',
+ epicId: 'None',
weight: 'None',
};
@@ -176,10 +187,10 @@ export const urlParams = {
'not[label_name][]': ['live action', 'drama'],
my_reaction_emoji: 'thumbsup',
confidential: 'no',
- iteration_title: 'season: #4',
- 'not[iteration_title]': 'season: #20',
- epic_id: 'gitlab-org%3A%3A%2612',
- 'not[epic_id]': 'gitlab-org::&34',
+ iteration_id: '4',
+ 'not[iteration_id]': '20',
+ epic_id: '12',
+ 'not[epic_id]': '34',
weight: '1',
'not[weight]': '3',
};
diff --git a/spec/frontend/issues_list/utils_spec.js b/spec/frontend/issues_list/utils_spec.js
index e377c35a0aa..b7863068570 100644
--- a/spec/frontend/issues_list/utils_spec.js
+++ b/spec/frontend/issues_list/utils_spec.js
@@ -8,10 +8,11 @@ import {
urlParams,
urlParamsWithSpecialValues,
} from 'jest/issues_list/mock_data';
-import { API_PARAM, DUE_DATE_VALUES, URL_PARAM, urlSortParams } from '~/issues_list/constants';
+import { DUE_DATE_VALUES, urlSortParams } from '~/issues_list/constants';
import {
- convertToParams,
+ convertToApiParams,
convertToSearchQuery,
+ convertToUrlParams,
getDueDateValue,
getFilterTokens,
getSortKey,
@@ -20,7 +21,7 @@ import {
describe('getSortKey', () => {
it.each(Object.keys(urlSortParams))('returns %s given the correct inputs', (sortKey) => {
- const { sort } = urlSortParams[sortKey];
+ const sort = urlSortParams[sortKey];
expect(getSortKey(sort)).toBe(sortKey);
});
});
@@ -80,31 +81,23 @@ describe('getFilterTokens', () => {
});
});
-describe('convertToParams', () => {
+describe('convertToApiParams', () => {
it('returns api params given filtered tokens', () => {
- expect(convertToParams(filteredTokens, API_PARAM)).toEqual({
- ...apiParams,
- epic_id: 'gitlab-org::&12',
- });
+ expect(convertToApiParams(filteredTokens)).toEqual(apiParams);
});
it('returns api params given filtered tokens with special values', () => {
- expect(convertToParams(filteredTokensWithSpecialValues, API_PARAM)).toEqual(
- apiParamsWithSpecialValues,
- );
+ expect(convertToApiParams(filteredTokensWithSpecialValues)).toEqual(apiParamsWithSpecialValues);
});
+});
+describe('convertToUrlParams', () => {
it('returns url params given filtered tokens', () => {
- expect(convertToParams(filteredTokens, URL_PARAM)).toEqual({
- ...urlParams,
- epic_id: 'gitlab-org::&12',
- });
+ expect(convertToUrlParams(filteredTokens)).toEqual(urlParams);
});
it('returns url params given filtered tokens with special values', () => {
- expect(convertToParams(filteredTokensWithSpecialValues, URL_PARAM)).toEqual(
- urlParamsWithSpecialValues,
- );
+ expect(convertToUrlParams(filteredTokensWithSpecialValues)).toEqual(urlParamsWithSpecialValues);
});
});