Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 156 additions & 13 deletions x-pack/test/api_integration/apis/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,53 @@
*/

import expect from '@kbn/expect';
import type { Context } from 'mocha';
import { FtrProviderContext } from '../../ftr_provider_context';
import { verifyErrorResponse } from '../../../../../test/api_integration/apis/search/verify_error';

export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const es = getService('es');
const log = getService('log');
const retry = getService('retry');

describe('search', function () {
this.onlyEsVersion('<=7');
const shardDelayAgg = (delay: string) => ({
aggs: {
delay: {
shard_delay: {
value: delay,
},
},
},
});

async function markRequiresShardDelayAgg(testContext: Context) {
const { body } = await es.info();
if (!body.version.number.includes('SNAPSHOT')) {
log.debug('Skipping because this build does not have the required shard_delay agg');
testContext.skip();
}
}

// https://github.com/elastic/kibana/issues/113082
describe.skip('post', () => {
it('should return 200 with final response if wait_for_completion_timeout is long enough', async () => {
describe('search', () => {
before(async () => {
// ensure es not empty
await es.index({
index: 'search-api-test',
id: 'search-api-test-doc',
body: { message: 'test doc' },
refresh: 'wait_for',
});
});
after(async () => {
await es.indices.delete({
index: 'search-api-test',
});
});

describe('post', () => {
it('should return 200 with final response without search id if wait_for_completion_timeout is long enough', async function () {
const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
Expand All @@ -29,7 +63,7 @@ export default function ({ getService }: FtrProviderContext) {
match_all: {},
},
},
wait_for_completion_timeout: '1000s',
wait_for_completion_timeout: '10s',
},
})
.expect(200);
Expand All @@ -41,7 +75,9 @@ export default function ({ getService }: FtrProviderContext) {
expect(resp.body).to.have.property('rawResponse');
});

it('should return 200 with partial response if wait_for_completion_timeout is not long enough', async () => {
it('should return 200 with search id and partial response if wait_for_completion_timeout is not long enough', async function () {
await markRequiresShardDelayAgg(this);

const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
Expand All @@ -51,6 +87,7 @@ export default function ({ getService }: FtrProviderContext) {
query: {
match_all: {},
},
...shardDelayAgg('3s'),
},
wait_for_completion_timeout: '1ms',
},
Expand All @@ -64,7 +101,9 @@ export default function ({ getService }: FtrProviderContext) {
expect(resp.body).to.have.property('rawResponse');
});

it('should retrieve results with id', async () => {
it('should retrieve results from completed search with search id', async function () {
await markRequiresShardDelayAgg(this);

const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
Expand All @@ -74,15 +113,58 @@ export default function ({ getService }: FtrProviderContext) {
query: {
match_all: {},
},
...shardDelayAgg('3s'),
},
wait_for_completion_timeout: '1ms',
},
})
.expect(200);

const { id } = resp.body;
expect(id).not.to.be(undefined);
expect(resp.body.isPartial).to.be(true);
expect(resp.body.isRunning).to.be(true);

await new Promise((resolve) => setTimeout(resolve, 3000));

await retry.tryForTime(10000, async () => {
const resp2 = await supertest
.post(`/internal/search/ese/${id}`)
.set('kbn-xsrf', 'foo')
.send({})
.expect(200);

expect(resp2.body.id).not.to.be(undefined);
expect(resp2.body.isPartial).to.be(false);
expect(resp2.body.isRunning).to.be(false);

return true;
});
});

await new Promise((resolve) => setTimeout(resolve, 2000));
it('should retrieve results from in-progress search with search id', async function () {
await markRequiresShardDelayAgg(this);

const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
.send({
params: {
body: {
query: {
match_all: {},
},
...shardDelayAgg('10s'),
},
wait_for_completion_timeout: '1ms',
},
})
.expect(200);

const { id } = resp.body;
expect(id).not.to.be(undefined);
expect(resp.body.isPartial).to.be(true);
expect(resp.body.isRunning).to.be(true);

const resp2 = await supertest
.post(`/internal/search/ese/${id}`)
Expand All @@ -91,8 +173,8 @@ export default function ({ getService }: FtrProviderContext) {
.expect(200);

expect(resp2.body.id).not.to.be(undefined);
expect(resp2.body.isPartial).to.be(false);
expect(resp2.body.isRunning).to.be(false);
expect(resp2.body.isPartial).to.be(true);
expect(resp2.body.isRunning).to.be(true);
});

it('should fail without kbn-xref header', async () => {
Expand Down Expand Up @@ -149,7 +231,7 @@ export default function ({ getService }: FtrProviderContext) {
verifyErrorResponse(resp.body, 400, 'illegal_argument_exception', true);
});

it('should return 404 if unkown id is provided', async () => {
it('should return 404 if unknown id is provided', async () => {
const resp = await supertest
.post(
`/internal/search/ese/FkxOb21iV1g2VGR1S2QzaWVtRU9fMVEbc3JWeWc1VHlUdDZ6MENxcXlYVG1Fdzo2NDg4`
Expand Down Expand Up @@ -266,7 +348,9 @@ export default function ({ getService }: FtrProviderContext) {
verifyErrorResponse(resp.body, 400, 'illegal_argument_exception', true);
});

it('should delete a search', async () => {
it('should delete an in-progress search', async function () {
await markRequiresShardDelayAgg(this);

const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
Expand All @@ -276,13 +360,72 @@ export default function ({ getService }: FtrProviderContext) {
query: {
match_all: {},
},
...shardDelayAgg('10s'),
},
wait_for_completion_timeout: '1ms',
},
})
.expect(200);

const { id } = resp.body;
expect(id).not.to.be(undefined);
expect(resp.body.isPartial).to.be(true);
expect(resp.body.isRunning).to.be(true);

await supertest
.delete(`/internal/search/ese/${id}`)
.set('kbn-xsrf', 'foo')
.send()
.expect(200);

// try to re-fetch
await supertest
.post(`/internal/search/ese/${id}`)
.set('kbn-xsrf', 'foo')
.send({})
.expect(404);
});

it('should delete a completed search', async function () {
await markRequiresShardDelayAgg(this);

const resp = await supertest
.post(`/internal/search/ese`)
.set('kbn-xsrf', 'foo')
.send({
params: {
body: {
query: {
match_all: {},
},
...shardDelayAgg('3s'),
},
wait_for_completion_timeout: '1ms',
},
})
.expect(200);

const { id } = resp.body;
expect(id).not.to.be(undefined);
expect(resp.body.isPartial).to.be(true);
expect(resp.body.isRunning).to.be(true);

await new Promise((resolve) => setTimeout(resolve, 3000));

await retry.tryForTime(10000, async () => {
const resp2 = await supertest
.post(`/internal/search/ese/${id}`)
.set('kbn-xsrf', 'foo')
.send({})
.expect(200);

expect(resp2.body.id).not.to.be(undefined);
expect(resp2.body.isPartial).to.be(false);
expect(resp2.body.isRunning).to.be(false);

return true;
});

await supertest
.delete(`/internal/search/ese/${id}`)
.set('kbn-xsrf', 'foo')
Expand Down