-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Cases] Fixing issue with find api total response #94971
[Cases] Fixing issue with find api total response #94971
Conversation
afterEach(async () => { | ||
await deleteAllCaseItems(es); | ||
}); | ||
describe('basic tests', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes are because I created a new describe
block for the already existing tests and for the new pagination tests. These changes are really just bringing the older tests under the new describe block and indentation.
}, | ||
], | ||
count_open_cases: 1, | ||
describe('find_cases pagination', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where the new tests begin.
Pinging @elastic/security-threat-hunting (Team:Threat Hunting) |
@XavierM question about the |
@@ -6,246 +6,454 @@ | |||
*/ | |||
|
|||
import expect from '@kbn/expect'; | |||
import supertestAsPromised from 'supertest-as-promised'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: As of 2.0.0 supertest
supports native promised and supertest-as-promised
is not needed. Do you need this only for the type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's just needed for the type because I'm putting all the promises in an array like this:
const responsePromises: supertestAsPromised.Test[] = [];
That was the location that vscode thought the type was defined 🤷♂️
expect(body.count_closed_cases).to.eql(0); | ||
expect(body.count_in_progress_cases).to.eql(0); | ||
|
||
const allCases = await getAllCasesSortedByCreatedAtAsc(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read your comment on top of this function but still I don't get why we need this to validate the cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the confusion, I'll see if I can describe issue here. Essentially, for the tests that walk the pages I wanted some way to verify that the cases returned by the _find
API were in the correct order (and actually on that page). To do that we need a reliable way to retrieve all the cases and then we can compare the chunk that the _find
API returns for a specific page.
For example if the test requests page 2 with a per_page of 2 when there are 10 total cases (say case, 0,1,2,3,4,5 etc created in that order), then the find API retrieve cases 2 and 3 (0 and 1 would be on the first page). So we need a source of truth ideally separate from the find API to gather all the cases and then compare the find results against that ground truth.
So then the question is how can we ensure that specific cases will be on a specific page for pagination. We could make 10 create API requests one at a time that each create a case. This would guarantee that the created_at
field of the 10 cases would be in ascending order and we could get away with just comparing the find response's created_at
to the response from the create API in the test setup. Unfortunately, creating cases one at a time was pretty slow.
Another option would be not have the sorting be on the created_at
field. For example if we could set each case title
to a deterministic value as we create the tests then we'd know what the order would be when the find API is paginating through them. Unfortunately, the case backend implementation only allows us to sort on a few fields and title
isn't allowed.
So the only fast solution I could think of was to create the cases using a Promise.all
and use an outside method (using Elasticsearch directly to retrieve the cases in sorted order) to retrieve all the cases. Promise.all
doesn't guarantee that for a specific i
in the loop that the case's created_at
date would be in order because they're being done asynchronously. The loop goes from 0-9 but case 9 could be created before 0 for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see! Now all make sense. Thanks for the detailed explanation!
I left some nit comments. Ignore them as we are in hurry and this fix must get into 7.12 the soonest possible. This changes need to be merge on master and 7.x, right?
You are right. There is no need for the |
Yeah it does need to be in 7.x and master. We ran into some problems with master though because with the introduction of sub cases and empty collections it's more difficult to accurately calculate the correct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code review ✅
manual testing ✅
thanks for the fix and the tests to confirm. LGTM 🏁
@elasticmachine merge upstream |
💚 Build SucceededMetrics [docs]
History
To update your PR or re-run it, just comment with: |
Summary
This PR address the bug described here: #94929 where the
_find
cases API does not return the correct value for thetotal
field. This makes the UI think there are no additional cases and therefore breaks the pagination functionality.The backend was incorrectly setting the
total
field to be the number of cases that were returned by the saved objects find call. Instead it should be setting thetotal
field to the returnedtotal
attribute in the saved objects client response.GIF of it working
Checklist