Skip to content

Commit

Permalink
feat(chat-e2e): message template tests (#2820)
Browse files Browse the repository at this point in the history
  • Loading branch information
irinakartun authored Dec 19, 2024
1 parent 54b0aec commit 6cac0cc
Show file tree
Hide file tree
Showing 29 changed files with 1,192 additions and 131 deletions.
17 changes: 13 additions & 4 deletions apps/chat-e2e/src/assertions/api/apiAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,19 @@ export class ApiAssertion {
.toBe(expectedTemperature);
}

public async assertRequestPrompt(request: ChatBody, expectedPrompt: string) {
expect
.soft(request.prompt, ExpectedMessages.chatRequestPromptIsValid)
.toBe(expectedPrompt);
public async assertRequestPrompt(
request: ChatBody,
expectedPrompt: string | undefined,
) {
if (request.prompt === undefined) {
expect
.soft(request.prompt, ExpectedMessages.chatRequestPromptIsValid)
.toBeUndefined();
} else {
expect
.soft(request.prompt, ExpectedMessages.chatRequestPromptIsValid)
.toBe(expectedPrompt);
}
}

public async assertRequestAddons(
Expand Down
30 changes: 25 additions & 5 deletions apps/chat-e2e/src/assertions/baseAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ export class BaseAssertion {
.toHaveText(expectedText);
}

public async assertElementAttribute(
element: BaseElement | Locator,
attribute: string,
expectedValue: string,
expectedMessage?: string,
) {
const elementLocator =
element instanceof BaseElement
? element.getElementLocator()
: (element as Locator);
await expect
.soft(
elementLocator,
expectedMessage ?? ExpectedMessages.elementAttributeValueIsValid,
)
.toHaveAttribute(attribute, expectedValue);
}

public async assertElementColor(element: BaseElement, expectedColor: string) {
const style = await element.getComputedStyleProperty(Styles.color);
expect
Expand All @@ -147,14 +165,16 @@ export class BaseAssertion {
}

public async assertElementsCount(
element: BaseElement,
element: BaseElement | Locator,
expectedCount: number,
) {
const elementsCount =
element instanceof BaseElement
? await element.getElementsCount()
: await element.count();

expect
.soft(
await element.getElementsCount(),
ExpectedMessages.elementsCountIsValid,
)
.soft(elementsCount, ExpectedMessages.elementsCountIsValid)
.toBe(expectedCount);
}
}
10 changes: 4 additions & 6 deletions apps/chat-e2e/src/assertions/chatMessagesAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,14 @@ export class ChatMessagesAssertion extends BaseAssertion {
message: string | number,
expectedState: ElementState,
) {
const chatMessage = this.chatMessages.getChatMessage(message);
await chatMessage.scrollIntoViewIfNeeded();
await chatMessage.hover();
const editIcon = this.chatMessages.setMessageTemplateIcon(chatMessage);
const chatMessage = await this.chatMessages.hoverOverMessage(message);
const templateIcon = this.chatMessages.setMessageTemplateIcon(chatMessage);
expectedState === 'visible'
? await expect
.soft(editIcon, ExpectedMessages.buttonIsVisible)
.soft(templateIcon, ExpectedMessages.buttonIsVisible)
.toBeVisible()
: await expect
.soft(editIcon, ExpectedMessages.buttonIsNotVisible)
.soft(templateIcon, ExpectedMessages.buttonIsNotVisible)
.toBeHidden();
}

Expand Down
11 changes: 11 additions & 0 deletions apps/chat-e2e/src/assertions/messageTemplateModalAssertion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { BaseAssertion } from '@/src/assertions/baseAssertion';
import { MessageTemplateModal } from '@/src/ui/webElements';

export class MessageTemplateModalAssertion extends BaseAssertion {
readonly messageTemplateModal: MessageTemplateModal;

constructor(messageTemplateModal: MessageTemplateModal) {
super();
this.messageTemplateModal = messageTemplateModal;
}
}
14 changes: 14 additions & 0 deletions apps/chat-e2e/src/core/dialFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ChatNotFound,
ConversationSettingsModal,
ConversationToCompare,
MessageTemplateModal,
PromptBar,
PublishingRules,
SelectFolderModal,
Expand Down Expand Up @@ -52,6 +53,7 @@ import {
import { AddonsDialogAssertion } from '@/src/assertions/addonsDialogAssertion';
import { ConversationToPublishAssertion } from '@/src/assertions/conversationToPublishAssertion';
import { ManageAttachmentsAssertion } from '@/src/assertions/manageAttachmentsAssertion';
import { MessageTemplateModalAssertion } from '@/src/assertions/messageTemplateModalAssertion';
import { SelectFolderModalAssertion } from '@/src/assertions/selectFolderModalAssertion';
import { SettingsModalAssertion } from '@/src/assertions/settingsModalAssertion';
import { SideBarEntityAssertion } from '@/src/assertions/sideBarEntityAssertion';
Expand Down Expand Up @@ -219,6 +221,7 @@ const dialTest = test.extend<
selectFolderModal: SelectFolderModal;
selectFolders: Folders;
attachedAllFiles: Folders;
messageTemplateModal: MessageTemplateModal;
manageAttachmentsAssertion: ManageAttachmentsAssertion;
settingsModal: SettingsModal;
publishingRequestModal: PublishingRequestModal;
Expand Down Expand Up @@ -273,6 +276,7 @@ const dialTest = test.extend<
conversationToPublishAssertion: ConversationToPublishAssertion;
folderToPublishAssertion: PublishFolderAssertion<FolderConversationsToPublish>;
organizationFolderConversationAssertions: FolderAssertion<Folders>;
messageTemplateModalAssertion: MessageTemplateModalAssertion;
}
>({
// eslint-disable-next-line no-empty-pattern
Expand Down Expand Up @@ -696,6 +700,10 @@ const dialTest = test.extend<
const attachedAllFiles = attachFilesModal.getAllFolderFiles();
await use(attachedAllFiles);
},
messageTemplateModal: async ({ page }, use) => {
const messageTemplateModal = new MessageTemplateModal(page);
await use(messageTemplateModal);
},
settingsModal: async ({ page }, use) => {
const settingsModal = new SettingsModal(page);
await use(settingsModal);
Expand Down Expand Up @@ -972,6 +980,12 @@ const dialTest = test.extend<
const shareApiAssertion = new ShareApiAssertion();
await use(shareApiAssertion);
},
messageTemplateModalAssertion: async ({ messageTemplateModal }, use) => {
const messageTemplateModalAssertion = new MessageTemplateModalAssertion(
messageTemplateModal,
);
await use(messageTemplateModalAssertion);
},
});

export default dialTest;
46 changes: 33 additions & 13 deletions apps/chat-e2e/src/testData/conversationHistory/conversationData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { FolderData } from '@/src/testData/folders/folderData';
import { ItemUtil } from '@/src/utils';
import { DateUtil } from '@/src/utils/dateUtil';
import { GeneratorUtil } from '@/src/utils/generatorUtil';
import { Message, MessageSettings, Role, Stage } from '@epam/ai-dial-shared';
import {
Message,
MessageSettings,
Role,
Stage,
TemplateMapping,
} from '@epam/ai-dial-shared';

export interface FolderConversation {
conversations: Conversation[];
Expand Down Expand Up @@ -96,8 +102,8 @@ export class ConversationData extends FolderData {
}

public prepareModelConversationBasedOnRequests(
model: DialAIEntityModel | string,
requests: string[],
model?: DialAIEntityModel | string,
name?: string,
) {
const basicConversation = this.prepareEmptyConversation(model, name);
Expand Down Expand Up @@ -136,8 +142,8 @@ export class ConversationData extends FolderData {
requests[i] = `${i} + ${i + 1} =`;
}
const basicConversation = this.prepareModelConversationBasedOnRequests(
models[models.length - 1],
requests,
models[models.length - 1],
);
const messages = basicConversation.messages;
for (let i = 0; i < models.length; i++) {
Expand All @@ -158,12 +164,12 @@ export class ConversationData extends FolderData {
}

public prepareConversationBasedOnPrompt(
prompt: Prompt,
prompt: Prompt | string,
params?: Map<string, string>,
model?: DialAIEntityModel | string,
name?: string,
) {
let promptContent = prompt.content!;
let promptContent = typeof prompt === 'string' ? prompt : prompt.content!;
const paramRegex = (param: string) =>
new RegExp('\\{\\{' + `(${param}.*?)` + '\\}\\}');
const defaultParamValueRegex = '(?<=\\|)(.*?)(?=\\}})';
Expand All @@ -178,19 +184,19 @@ export class ConversationData extends FolderData {
}
}
//set default prompt parameters if absent in params map
const matchedDefaultValue = promptContent.match(defaultParamValueRegex);
if (matchedDefaultValue) {
promptContent = promptContent.replace(
paramRegex(''),
matchedDefaultValue[0],
);
}
const matchedDefaultValues = promptContent.matchAll(
new RegExp(defaultParamValueRegex, 'g'),
);
Array.from(matchedDefaultValues, (match) => {
promptContent = promptContent.replace(paramRegex(''), match[0]);
});

const conversation = this.prepareDefaultConversation(model, name);
const userMessages = conversation.messages.filter((m) => m.role === 'user');

userMessages.forEach((m) => {
(m.templateMapping! as Record<string, string>)[promptContent] =
prompt.content!;
typeof prompt === 'string' ? prompt : prompt.content!;
m.content = promptContent;
});
return conversation;
Expand Down Expand Up @@ -788,4 +794,18 @@ export class ConversationData extends FolderData {
replayConversation.replay.replayAsIs = true;
return replayConversation;
}

public prepareConversationBasedOnMessageTemplate(
request: string,
templateMap: Map<string, string>,
) {
const conversation = this.prepareModelConversationBasedOnRequests([
request,
]);
const userMessage = conversation.messages.find((m) => m.role === 'user')!;
const templateMapping: TemplateMapping[] = [];
templateMap.forEach((k, v) => templateMapping.push([v, k]));
userMessage.templateMapping = templateMapping;
return conversation;
}
}
13 changes: 13 additions & 0 deletions apps/chat-e2e/src/testData/expectedConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,19 @@ export const ExpectedConstants = {
const namesString = names.map((name) => `"${name}"`).join(', ');
return `${namesString} have already been unpublished. You can't approve this request.`;
},
messageTemplateModalTitle: 'Message template',
messageTemplateModalDescription:
'Copy a part of the message into the first input and provide a template with template variables into the second input',
messageTemplateModalOriginalMessageLabel: 'Original message:',
messageTemplateContentPlaceholder: 'A part of the message',
messageTemplateValuePlaceholder:
'Your template. Use {{}} to denote a variable',
originalMessageTemplateErrorMessage:
'This part was not found in the original message',
messageTemplateMissingVarErrorMessage:
'Template must have at least one variable',
messageTemplateRequiredField: 'Please fill in this required field',
messageTemplateMismatchTextErrorMessage: `Template doesn't match the message text`,
};

export enum Types {
Expand Down
9 changes: 3 additions & 6 deletions apps/chat-e2e/src/tests/abortedReplay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ dialTest(
async () => {
firstConversation =
conversationData.prepareModelConversationBasedOnRequests(
firstRandomModel,
[firstUserRequest],
firstRandomModel,
);
conversationData.resetData();
secondConversation =
conversationData.prepareModelConversationBasedOnRequests(
secondRandomModel,
[secondUserRequest],
secondRandomModel,
);
conversationData.resetData();
historyConversation = conversationData.prepareHistoryConversation(
Expand Down Expand Up @@ -392,10 +392,7 @@ dialTest(
requests.push(GeneratorUtil.randomString(200));
}
const conversation =
conversationData.prepareModelConversationBasedOnRequests(
defaultModel,
requests,
);
conversationData.prepareModelConversationBasedOnRequests(requests);
replayConversation =
conversationData.prepareDefaultReplayConversation(conversation);
await dataInjector.createConversations([
Expand Down
2 changes: 1 addition & 1 deletion apps/chat-e2e/src/tests/accountSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ dialTest(
const request = GeneratorUtil.randomString(170);
const name = GeneratorUtil.randomString(170);
conversation = conversationData.prepareModelConversationBasedOnRequests(
ModelsUtil.getDefaultModel()!,
[request],
ModelsUtil.getDefaultModel()!,
name,
);
await dataInjector.createConversations([conversation]);
Expand Down
4 changes: 2 additions & 2 deletions apps/chat-e2e/src/tests/chatApi/entitySimpleRequest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ for (const entity of entitySimpleRequests) {
dialTest.skip(process.env.E2E_HOST === undefined, skipReason);
const conversation =
conversationData.prepareModelConversationBasedOnRequests(
entity.entityId,
[entity.request],
entity.entityId,
);
if (entity.systemPrompt) {
conversation.prompt = entity.systemPrompt;
Expand Down Expand Up @@ -48,8 +48,8 @@ dialTest(
);
const conversation =
conversationData.prepareModelConversationBasedOnRequests(
replayEntity.entityId,
[replayEntity.request],
replayEntity.entityId,
);
conversationData.resetData();
const replayConversation =
Expand Down
7 changes: 2 additions & 5 deletions apps/chat-e2e/src/tests/chatBarConversation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1200,10 +1200,7 @@ dialTest(
conversationData.resetData();

const firstConversation =
conversationData.prepareModelConversationBasedOnRequests(
defaultModel,
[request],
);
conversationData.prepareModelConversationBasedOnRequests([request]);
firstConversation.folderId = firstFolder.id;
firstConversation.id = `${firstConversation.folderId}/${firstConversation.id}`;
conversationData.resetData();
Expand All @@ -1221,8 +1218,8 @@ dialTest(

const thirdConversation =
conversationData.prepareModelConversationBasedOnRequests(
defaultModel,
[request],
defaultModel,
specialSymbolsName(),
);
thirdConversation.folderId = secondFolder.id;
Expand Down
2 changes: 1 addition & 1 deletion apps/chat-e2e/src/tests/chatExportImport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ dialTest(
async () => {
importedRootConversation =
conversationData.prepareModelConversationBasedOnRequests(
simpleRequestModel!,
requests,
simpleRequestModel!,
);
threeConversationsData = ImportConversation.prepareConversationFile(
importedRootConversation,
Expand Down
9 changes: 5 additions & 4 deletions apps/chat-e2e/src/tests/chatHeader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,11 @@ dialTest(
setTestIds('EPMRTC-490', 'EPMRTC-491');
let conversation: Conversation;
await dialTest.step('Prepare conversation with history', async () => {
conversation = conversationData.prepareModelConversationBasedOnRequests(
defaultModel,
['first request', 'second request', 'third request'],
);
conversation = conversationData.prepareModelConversationBasedOnRequests([
'first request',
'second request',
'third request',
]);
await dataInjector.createConversations([conversation]);
});

Expand Down
Loading

0 comments on commit 6cac0cc

Please sign in to comment.