Skip to content

Commit

Permalink
Migrating existing conversations.spec.ts test to to deployment-agnost…
Browse files Browse the repository at this point in the history
…ic test
  • Loading branch information
arturoliduena committed Dec 27, 2024
1 parent 2c2af4a commit 88d83cf
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import expect from '@kbn/expect';
import { merge, omit } from 'lodash';
import {
type ConversationCreateRequest,
type ConversationUpdateRequest,
MessageRole,
} from '@kbn/observability-ai-assistant-plugin/common/types';
import type { SupertestReturnType } from '../../../../services/observability_ai_assistant_api';
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) {
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi');

const conversationCreate: ConversationCreateRequest = {
'@timestamp': new Date().toISOString(),
conversation: {
title: 'My title',
},
labels: {},
numeric_labels: {},
messages: [
{
'@timestamp': new Date().toISOString(),
message: {
role: MessageRole.User,
content: 'My message',
},
},
],
public: false,
};

const conversationUpdate: ConversationUpdateRequest = merge({}, conversationCreate, {
conversation: {
id: '<conversationCreate.id>',
title: 'My updated title',
},
});

describe('Conversations', () => {
describe('without conversations', () => {
it('returns no conversations when listing', async () => {
const { status, body } = await observabilityAIAssistantAPIClient.editor({
endpoint: 'POST /internal/observability_ai_assistant/conversations',
});

expect(status).to.be(200);

expect(body).to.eql({ conversations: [] });
});

it('returns a 404 for updating conversations', async () => {
try {
await observabilityAIAssistantAPIClient.editor({
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: 'non-existing-conversation-id',
},
body: {
conversation: conversationUpdate,
},
},
});
} catch (error) {
expect(error.status).to.be(404);
}
});

it('returns a 404 for retrieving a conversation', async () => {
try {
await observabilityAIAssistantAPIClient.editor({
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: 'my-conversation-id',
},
},
});
} catch (error) {
expect(error.status).to.be(404);
}
});
});

describe('when creating a conversation with the write user', () => {
let createResponse: Awaited<
SupertestReturnType<'POST /internal/observability_ai_assistant/conversation'>
>;
before(async () => {
createResponse = await observabilityAIAssistantAPIClient.editor({
endpoint: 'POST /internal/observability_ai_assistant/conversation',
params: {
body: {
conversation: conversationCreate,
},
},
});
expect(createResponse.status).to.be(200);
});

after(async () => {
const { status } = await observabilityAIAssistantAPIClient.editor({
endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: createResponse.body.conversation.id,
},
},
});
expect(status).to.be(200);

try {
await observabilityAIAssistantAPIClient.editor({
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: createResponse.body.conversation.id,
},
},
});
} catch (error) {
expect(error.status).to.be(404);
}
});

it('returns the conversation', () => {
// delete user from response to avoid comparing it as it will be different in MKI
// delete createResponse.body.user;
expect(createResponse.body).to.eql({
'@timestamp': createResponse.body['@timestamp'],
conversation: {
id: createResponse.body.conversation.id,
last_updated: createResponse.body.conversation.last_updated,
title: conversationCreate.conversation.title,
},
labels: conversationCreate.labels,
numeric_labels: conversationCreate.numeric_labels,
messages: conversationCreate.messages,
namespace: 'default',
public: conversationCreate.public,
user: {
id: 'u_gf3TRV5WWjD0PQCcTzkUyRE8By8uUt90gK-rT9ZPhA4_0',
name: 'elastic_editor',
},
});
});

it('returns a 404 for updating a non-existing conversation', async () => {
try {
await observabilityAIAssistantAPIClient.editor({
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: 'non-existing-conversation-id',
},
body: {
conversation: conversationUpdate,
},
},
});
} catch (error) {
expect(error.status).to.be(404);
}
});

it('returns a 404 for retrieving a non-existing conversation', async () => {
try {
await observabilityAIAssistantAPIClient.editor({
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: 'non-existing-conversation-id',
},
},
});
} catch (error) {
expect(error.status).to.be(404);
}
});

it('returns the conversation that was created', async () => {
const response = await observabilityAIAssistantAPIClient.editor({
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: createResponse.body.conversation.id,
},
},
});

expect(response.status).to.be(200);

expect(response.body).to.eql(createResponse.body);
});

it('returns the created conversation when listing', async () => {
const response = await observabilityAIAssistantAPIClient.editor({
endpoint: 'POST /internal/observability_ai_assistant/conversations',
});

expect(response.status).to.be(200);

expect(response.body.conversations[0]).to.eql(createResponse.body);
});
// TODO
it.skip('returns a 404 when reading it with another user', () => {});

describe('after updating', () => {
let updateResponse: Awaited<
SupertestReturnType<'PUT /internal/observability_ai_assistant/conversation/{conversationId}'>
>;

before(async () => {
updateResponse = await observabilityAIAssistantAPIClient.editor({
endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: createResponse.body.conversation.id,
},
body: {
conversation: merge(omit(conversationUpdate, 'conversation.id'), {
conversation: { id: createResponse.body.conversation.id },
}),
},
},
});
expect(updateResponse.status).to.be(200);
});

it('returns the updated conversation as response', async () => {
expect(updateResponse.body.conversation.title).to.eql(
conversationUpdate.conversation.title
);
});

it('returns the updated conversation after get', async () => {
const updateAfterCreateResponse = await observabilityAIAssistantAPIClient.editor({
endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}',
params: {
path: {
conversationId: createResponse.body.conversation.id,
},
},
});

expect(updateAfterCreateResponse.status).to.be(200);

expect(updateAfterCreateResponse.body.conversation.title).to.eql(
conversationUpdate.conversation.title
);
});
});
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) {
describe('conversations', () => {
loadTestFile(require.resolve('./conversations.spec.ts'));
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';

export default function aiAssistantApiIntegrationTests({
loadTestFile,
}: DeploymentAgnosticFtrProviderContext) {
describe('observability AI Assistant', function () {
loadTestFile(require.resolve('./conversations'));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext)
loadTestFile(require.resolve('../../apis/saved_objects_management'));
loadTestFile(require.resolve('../../apis/observability/slo'));
loadTestFile(require.resolve('../../apis/observability/synthetics'));
loadTestFile(require.resolve('../../apis/observability/ai_assistant'));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext)
loadTestFile(require.resolve('../../apis/observability/slo'));
loadTestFile(require.resolve('../../apis/observability/synthetics'));
loadTestFile(require.resolve('../../apis/observability/infra'));
loadTestFile(require.resolve('../../apis/observability/ai_assistant'));
});
}

0 comments on commit 88d83cf

Please sign in to comment.