[Cases] Fixing issue with find api total response (#94971)

* Fixing issue with find api total value

* Removing .only

* Adding more comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Jonathan Buttner 2021-03-22 11:47:38 -04:00 committed by GitHub
parent 8c16275644
commit c61bf997fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 413 additions and 201 deletions

View file

@ -66,11 +66,13 @@ export function initFindCasesApi({ caseService, router, logger }: RouteDeps) {
return response.ok({
body: CasesFindResponseRt.encode(
transformCases({
...cases,
casesMap: cases.casesMap,
page: cases.page,
perPage: cases.perPage,
total: cases.total,
countOpenCases: openCases,
countInProgressCases: inProgressCases,
countClosedCases: closedCases,
total: cases.casesMap.size,
})
),
});

View file

@ -193,6 +193,7 @@ interface CasesMapWithPageInfo {
casesMap: Map<string, CaseResponse>;
page: number;
perPage: number;
total: number;
}
type FindCaseOptions = CasesFindRequest & SavedObjectFindOptions;
@ -345,6 +346,7 @@ export class CaseService implements CaseServiceSetup {
casesMap: casesWithComments,
page: cases.page,
perPage: cases.per_page,
total: cases.total,
};
}

View file

@ -6,246 +6,454 @@
*/
import expect from '@kbn/expect';
import supertestAsPromised from 'supertest-as-promised';
import { SearchResponse } from 'elasticsearch';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { CASES_URL } from '../../../../../plugins/case/common/constants';
import { postCaseReq, postCommentUserReq, findCasesResp } from '../../../common/lib/mock';
import { deleteAllCaseItems } from '../../../common/lib/utils';
import { CasesFindResponse } from '../../../../../plugins/case/common/api';
interface CaseAttributes {
cases: {
title: string;
};
}
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext): void => {
const supertest = getService('supertest');
const es = getService('es');
describe('find_cases', () => {
afterEach(async () => {
await deleteAllCaseItems(es);
});
it('should return empty response', async () => {
const { body } = await supertest
.get(`${CASES_URL}/_find`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql(findCasesResp);
});
it('should return cases', async () => {
const { body: a } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
const { body: b } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
const { body: c } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 3,
cases: [a, b, c],
count_open_cases: 3,
describe('basic tests', () => {
afterEach(async () => {
await deleteAllCaseItems(es);
});
});
it('filters by tags', async () => {
await supertest.post(CASES_URL).set('kbn-xsrf', 'true').send(postCaseReq);
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send({ ...postCaseReq, tags: ['unique'] })
.expect(200);
it('should return empty response', async () => {
const { body } = await supertest
.get(`${CASES_URL}/_find`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&tags=unique`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [postedCase],
count_open_cases: 1,
expect(body).to.eql(findCasesResp);
});
});
it('filters by status', async () => {
const { body: openCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
it('should return cases', async () => {
const { body: a } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
const { body: toCloseCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
const { body: b } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
const { body: c } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 3,
cases: [a, b, c],
count_open_cases: 3,
});
});
it('filters by tags', async () => {
await supertest.post(CASES_URL).set('kbn-xsrf', 'true').send(postCaseReq);
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send({ ...postCaseReq, tags: ['unique'] })
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&tags=unique`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [postedCase],
count_open_cases: 1,
});
});
it('filters by status', async () => {
const { body: openCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
const { body: toCloseCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
cases: [
{
id: toCloseCase.id,
version: toCloseCase.version,
status: 'closed',
},
],
})
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&status=open`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [openCase],
count_open_cases: 1,
count_closed_cases: 1,
count_in_progress_cases: 0,
});
});
it('filters by reporters', async () => {
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&reporters=elastic`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [postedCase],
count_open_cases: 1,
});
});
it('correctly counts comments', async () => {
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
// post 2 comments
await supertest
.post(`${CASES_URL}/${postedCase.id}/comments`)
.set('kbn-xsrf', 'true')
.send(postCommentUserReq)
.expect(200);
const { body: patchedCase } = await supertest
.post(`${CASES_URL}/${postedCase.id}/comments`)
.set('kbn-xsrf', 'true')
.send(postCommentUserReq)
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [
{
id: toCloseCase.id,
version: toCloseCase.version,
status: 'closed',
...patchedCase,
comments: [],
totalComment: 2,
},
],
})
.expect(200);
count_open_cases: 1,
});
});
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&status=open`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
it('correctly counts open/closed/in-progress', async () => {
await supertest.post(CASES_URL).set('kbn-xsrf', 'true').send(postCaseReq);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [openCase],
count_open_cases: 1,
count_closed_cases: 1,
count_in_progress_cases: 0,
const { body: inProgreeCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
cases: [
{
id: postedCase.id,
version: postedCase.version,
status: 'closed',
},
],
})
.expect(200);
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
cases: [
{
id: inProgreeCase.id,
version: inProgreeCase.version,
status: 'in-progress',
},
],
})
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body.count_open_cases).to.eql(1);
expect(body.count_closed_cases).to.eql(1);
expect(body.count_in_progress_cases).to.eql(1);
});
it('unhappy path - 400s when bad query supplied', async () => {
await supertest
.get(`${CASES_URL}/_find?perPage=true`)
.set('kbn-xsrf', 'true')
.send()
.expect(400);
});
});
it('filters by reporters', async () => {
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc&reporters=elastic`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [postedCase],
count_open_cases: 1,
describe('find_cases pagination', () => {
const numCases = 10;
before(async () => {
await createCasesWithTitleAsNumber(numCases);
});
});
it('correctly counts comments', async () => {
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
after(async () => {
await deleteAllCaseItems(es);
});
// post 2 comments
await supertest
.post(`${CASES_URL}/${postedCase.id}/comments`)
.set('kbn-xsrf', 'true')
.send(postCommentUserReq)
.expect(200);
const createCasesWithTitleAsNumber = async (total: number) => {
const responsePromises: supertestAsPromised.Test[] = [];
for (let i = 0; i < total; i++) {
// this doesn't guarantee that the cases will be created in order that the for-loop executes,
// for example case with title '2', could be created before the case with title '1' since we're doing a promise all here
// A promise all is just much faster than doing it one by one which would have guaranteed that the cases are
// created in the order that the for-loop executes
responsePromises.push(
supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send({ ...postCaseReq, title: `${i}` })
);
}
const responses = await Promise.all(responsePromises);
return responses.map((response) => response.body);
};
const { body: patchedCase } = await supertest
.post(`${CASES_URL}/${postedCase.id}/comments`)
.set('kbn-xsrf', 'true')
.send(postCommentUserReq)
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body).to.eql({
...findCasesResp,
total: 1,
cases: [
{
...patchedCase,
comments: [],
totalComment: 2,
/**
* This is used to retrieve all the cases in the same sorted order that we're expecting them to come back via the
* _find API so that we have a more true comparison instead of using the _find API to get all the cases which
* could mangle the results if the implementation had a bug.
*
* Ideally we could enforce how the cases are created in reasonable time, waiting for each api call to finish takes
* around 30 seconds which seemed too slow
*/
const getAllCasesSortedByCreatedAtAsc = async () => {
const cases = await es.search<SearchResponse<CaseAttributes>>({
index: '.kibana',
body: {
size: 10000,
sort: [{ 'cases.created_at': { unmapped_type: 'date', order: 'asc' } }],
query: {
term: { type: 'cases' },
},
},
],
count_open_cases: 1,
});
return cases.body.hits.hits.map((hit) => hit._source);
};
it('returns the correct total when perPage is less than the total', async () => {
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
page: 1,
perPage: 5,
})
.set('kbn-xsrf', 'true')
.expect(200);
expect(body.cases.length).to.eql(5);
expect(body.total).to.eql(10);
expect(body.page).to.eql(1);
expect(body.per_page).to.eql(5);
expect(body.count_open_cases).to.eql(10);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
});
});
it('correctly counts open/closed/in-progress', async () => {
await supertest.post(CASES_URL).set('kbn-xsrf', 'true').send(postCaseReq);
it('returns the correct total when perPage is greater than the total', async () => {
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
page: 1,
perPage: 11,
})
.set('kbn-xsrf', 'true')
.expect(200);
const { body: inProgreeCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq);
expect(body.total).to.eql(10);
expect(body.page).to.eql(1);
expect(body.per_page).to.eql(11);
expect(body.cases.length).to.eql(10);
expect(body.count_open_cases).to.eql(10);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
});
const { body: postedCase } = await supertest
.post(CASES_URL)
.set('kbn-xsrf', 'true')
.send(postCaseReq)
.expect(200);
it('returns the correct total when perPage is equal to the total', async () => {
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
page: 1,
perPage: 10,
})
.set('kbn-xsrf', 'true')
.expect(200);
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
cases: [
{
id: postedCase.id,
version: postedCase.version,
status: 'closed',
},
],
})
.expect(200);
expect(body.total).to.eql(10);
expect(body.page).to.eql(1);
expect(body.per_page).to.eql(10);
expect(body.cases.length).to.eql(10);
expect(body.count_open_cases).to.eql(10);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
});
await supertest
.patch(CASES_URL)
.set('kbn-xsrf', 'true')
.send({
cases: [
{
id: inProgreeCase.id,
version: inProgreeCase.version,
status: 'in-progress',
},
],
})
.expect(200);
it('returns the second page of results', async () => {
const perPage = 5;
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
page: 2,
perPage,
})
.set('kbn-xsrf', 'true')
.expect(200);
const { body } = await supertest
.get(`${CASES_URL}/_find?sortOrder=asc`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
expect(body.total).to.eql(10);
expect(body.page).to.eql(2);
expect(body.per_page).to.eql(5);
expect(body.cases.length).to.eql(5);
expect(body.count_open_cases).to.eql(10);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
expect(body.count_open_cases).to.eql(1);
expect(body.count_closed_cases).to.eql(1);
expect(body.count_in_progress_cases).to.eql(1);
});
const allCases = await getAllCasesSortedByCreatedAtAsc();
it('unhappy path - 400s when bad query supplied', async () => {
await supertest
.get(`${CASES_URL}/_find?perPage=true`)
.set('kbn-xsrf', 'true')
.send()
.expect(400);
body.cases.map((caseInfo, index) => {
// we started on the second page of 10 cases with a perPage of 5, so the first case should 0 + 5 (index + perPage)
expect(caseInfo.title).to.eql(allCases[index + perPage].cases.title);
});
});
it('paginates with perPage of 2 through 10 total cases', async () => {
const total = 10;
const perPage = 2;
// it's less than or equal here because the page starts at 1, so page 5 is a valid page number
// and should have case titles 9, and 10
for (let currentPage = 1; currentPage <= total / perPage; currentPage++) {
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
page: currentPage,
perPage,
})
.set('kbn-xsrf', 'true')
.expect(200);
expect(body.total).to.eql(total);
expect(body.page).to.eql(currentPage);
expect(body.per_page).to.eql(perPage);
expect(body.cases.length).to.eql(perPage);
expect(body.count_open_cases).to.eql(total);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
const allCases = await getAllCasesSortedByCreatedAtAsc();
body.cases.map((caseInfo, index) => {
// for page 1, the cases tiles should be 0,1,2 for page 2: 3,4,5 etc (assuming the titles were sorted
// correctly)
expect(caseInfo.title).to.eql(
allCases[index + perPage * (currentPage - 1)].cases.title
);
});
}
});
it('retrieves the last three cases', async () => {
const { body }: { body: CasesFindResponse } = await supertest
.get(`${CASES_URL}/_find`)
.query({
sortOrder: 'asc',
// this should skip the first 7 cases and only return the last 3
page: 2,
perPage: 7,
})
.set('kbn-xsrf', 'true')
.expect(200);
expect(body.total).to.eql(10);
expect(body.page).to.eql(2);
expect(body.per_page).to.eql(7);
expect(body.cases.length).to.eql(3);
expect(body.count_open_cases).to.eql(10);
expect(body.count_closed_cases).to.eql(0);
expect(body.count_in_progress_cases).to.eql(0);
});
});
});
};