diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index 6ab944d61b8bc..1935aba9ac60a 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -69,7 +69,7 @@ describe('checking migration metadata changes on all registered SO types', () => "canvas-element": "c27505dcf2970760bea8a0fe1d000253f0c40f08", "canvas-workpad": "eb7b28a3b1c24af615edbf29becddf2e750a4bb5", "canvas-workpad-template": "34454b811e32993eaa55c6ec85a7aecca00c4cfc", - "cases": "7ff5ce930146a2d6fc8fbf536ce2ee16e9df296f", + "cases": "17af08c8b3550b3e57ba1a7f3b89d85f271712c0", "cases-comments": "d7c4c1d24e97620cd415e27e5eb7d5b5f2c5b461", "cases-configure": "1afc414f5563a36e4612fa269193d3ed7277c7bd", "cases-connector-mappings": "4b16d440af966e5d6e0fa33368bfa15d987a4b69", diff --git a/x-pack/plugins/cases/server/client/utils.test.ts b/x-pack/plugins/cases/server/client/utils.test.ts index 3e46e9dbae0e7..42989ca09aa8a 100644 --- a/x-pack/plugins/cases/server/client/utils.test.ts +++ b/x-pack/plugins/cases/server/client/utils.test.ts @@ -10,36 +10,40 @@ import { buildNestedFilter, buildRangeFilter, constructQueryOptions, - sortToSnake, + convertSortField, } from './utils'; import { toElasticsearchQuery } from '@kbn/es-query'; import { CaseStatuses } from '../../common'; import { CaseSeverity } from '../../common/api'; describe('utils', () => { - describe('sortToSnake', () => { + describe('convertSortField', () => { it('transforms status correctly', () => { - expect(sortToSnake('status')).toBe('status'); + expect(convertSortField('status')).toBe('status'); }); it('transforms createdAt correctly', () => { - expect(sortToSnake('createdAt')).toBe('created_at'); + expect(convertSortField('createdAt')).toBe('created_at'); }); it('transforms created_at correctly', () => { - expect(sortToSnake('created_at')).toBe('created_at'); + expect(convertSortField('created_at')).toBe('created_at'); }); it('transforms closedAt correctly', () => { - expect(sortToSnake('closedAt')).toBe('closed_at'); + expect(convertSortField('closedAt')).toBe('closed_at'); }); it('transforms closed_at correctly', () => { - expect(sortToSnake('closed_at')).toBe('closed_at'); + expect(convertSortField('closed_at')).toBe('closed_at'); + }); + + it('transforms title correctly', () => { + expect(convertSortField('title')).toBe('title.keyword'); }); it('transforms default correctly', () => { - expect(sortToSnake('not-exist')).toBe('created_at'); + expect(convertSortField('not-exist')).toBe('created_at'); }); }); diff --git a/x-pack/plugins/cases/server/client/utils.ts b/x-pack/plugins/cases/server/client/utils.ts index eff291e32bfa3..1851750d862d9 100644 --- a/x-pack/plugins/cases/server/client/utils.ts +++ b/x-pack/plugins/cases/server/client/utils.ts @@ -373,7 +373,7 @@ export const constructQueryOptions = ({ }: CasesFindQueryParams): SavedObjectFindOptionsKueryNode => { const tagsFilter = buildFilter({ filters: tags, field: 'tags', operator: 'or' }); const reportersFilter = createReportersFilter(reporters); - const sortField = sortToSnake(sortByField); + const sortField = convertSortField(sortByField); const ownerFilter = buildFilter({ filters: owner, field: OWNER_FIELD, operator: 'or' }); const statusFilter = status != null ? addStatusFilter({ status }) : undefined; @@ -494,9 +494,10 @@ enum SortFieldCase { closedAt = 'closed_at', createdAt = 'created_at', status = 'status', + title = 'title.keyword', } -export const sortToSnake = (sortField: string | undefined): SortFieldCase => { +export const convertSortField = (sortField: string | undefined): SortFieldCase => { switch (sortField) { case 'status': return SortFieldCase.status; @@ -506,6 +507,8 @@ export const sortToSnake = (sortField: string | undefined): SortFieldCase => { case 'closedAt': case 'closed_at': return SortFieldCase.closedAt; + case 'title': + return SortFieldCase.title; default: return SortFieldCase.createdAt; } diff --git a/x-pack/plugins/cases/server/saved_object_types/cases.ts b/x-pack/plugins/cases/server/saved_object_types/cases.ts index e0b9ab1cbafda..b34a355dfcd3e 100644 --- a/x-pack/plugins/cases/server/saved_object_types/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/cases.ts @@ -138,6 +138,11 @@ export const createCaseSavedObjectType = ( }, title: { type: 'text', + fields: { + keyword: { + type: 'keyword', + }, + }, }, status: { type: 'keyword', diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts index 3c076d4e35142..916e3c389232e 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts @@ -278,6 +278,24 @@ export default ({ getService }: FtrProviderContext): void => { } }); + it('sorts by title', async () => { + const case3 = await createCase(supertest, { ...postCaseReq, title: 'c' }); + const case2 = await createCase(supertest, { ...postCaseReq, title: 'b' }); + const case1 = await createCase(supertest, { ...postCaseReq, title: 'a' }); + + const cases = await findCases({ + supertest, + query: { sortField: 'title', sortOrder: 'asc' }, + }); + + expect(cases).to.eql({ + ...findCasesResp, + total: 3, + cases: [case1, case2, case3], + count_open_cases: 3, + }); + }); + it('unhappy path - 400s when bad query supplied', async () => { await findCases({ supertest, query: { perPage: true }, expectedHttpCode: 400 }); });