Skip to content

Commit

Permalink
feat(chat-e2e): footer and request token limits tests (epam#1807)
Browse files Browse the repository at this point in the history
Co-authored-by: Ilya Bondar <[email protected]>
  • Loading branch information
irinakartun and IlyaBondar authored Jul 24, 2024
1 parent 7945ad9 commit 5cf5fd5
Show file tree
Hide file tree
Showing 21 changed files with 413 additions and 11 deletions.
46 changes: 45 additions & 1 deletion apps/chat-e2e/src/assertions/chatMessagesAssertion.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExpectedMessages } from '@/src/testData';
import { ElementLabel, ElementState, ExpectedMessages } from '@/src/testData';
import { Styles } from '@/src/ui/domData';
import { ChatMessages } from '@/src/ui/webElements';
import { expect } from '@playwright/test';

Expand All @@ -19,4 +20,47 @@ export class ChatMessagesAssertion {
.soft(messageMaxWidth, ExpectedMessages.elementWidthIsValid)
.toBeHidden();
}

public async assertShowMoreLessButtonState(
label: ElementLabel,
expectedState: ElementState,
) {
const button =
label === 'more'
? this.chatMessages.showMoreButton.getElementLocator()
: this.chatMessages.showLessButton.getElementLocator();
expectedState === 'visible'
? await expect
.soft(button, ExpectedMessages.buttonIsVisible)
.toBeVisible()
: await expect
.soft(button, ExpectedMessages.buttonIsNotVisible)
.toBeHidden();
}

public async assertShowMoreLessButtonColor(
label: ElementLabel,
expectedColor: string,
) {
const button =
label === 'more'
? this.chatMessages.showMoreButton
: this.chatMessages.showLessButton;
const color = await button.getComputedStyleProperty(Styles.color);
expect
.soft(color[0], ExpectedMessages.elementColorIsValid)
.toBe(expectedColor);
}

public async assertMessageStagesCount(
messagesIndex: number,
expectedCount: number,
) {
const stagesCount = await this.chatMessages
.messageStages(messagesIndex)
.count();
expect
.soft(stagesCount, ExpectedMessages.elementsCountIsValid)
.toBe(expectedCount);
}
}
9 changes: 9 additions & 0 deletions apps/chat-e2e/src/assertions/confirmationDialogAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ export class ConfirmationDialogAssertion {
this.confirmationDialog = confirmationDialog;
}

public async assertConfirmationDialogTitle(expectedTitle: string) {
expect
.soft(
await this.confirmationDialog.entityName.getElementInnerContent(),
ExpectedMessages.modalDialogTitleIsValid,
)
.toBe(expectedTitle);
}

public async assertConfirmationMessage(expectedMessage: string) {
expect
.soft(
Expand Down
31 changes: 31 additions & 0 deletions apps/chat-e2e/src/assertions/footerAssertion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ElementState, ExpectedMessages } from '@/src/testData';
import { Footer } from '@/src/ui/webElements/footer';
import { expect } from '@playwright/test';

export class FooterAssertion {
readonly footer: Footer;

constructor(footer: Footer) {
this.footer = footer;
}

public async assertFooterState(expectedState: ElementState) {
const footer = this.footer.getElementLocator();
expectedState === 'visible'
? await expect
.soft(footer, ExpectedMessages.footerIsVisible)
.toBeVisible()
: await expect
.soft(footer, ExpectedMessages.footerIsNotVisible)
.toBeHidden();
}

public async assertFooterContentLength() {
expect
.soft(
await this.footer.getElementInnerContent().then((c) => c.length),
ExpectedMessages.footerContentIsNotEmpty,
)
.toBeGreaterThan(0);
}
}
7 changes: 7 additions & 0 deletions apps/chat-e2e/src/assertions/sendMessageAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,11 @@ export class SendMessageAssertion {
.soft(sendMessageInputFullWidth, ExpectedMessages.elementWidthIsValid)
.toBe(initialWidth);
}

public async assertMessageValue(expectedValue: string) {
const messageValue = await this.sendMessage.getMessage();
expect
.soft(messageValue, ExpectedMessages.messageContentIsValid)
.toBe(expectedValue);
}
}
6 changes: 6 additions & 0 deletions apps/chat-e2e/src/core/dialFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ChatMessagesAssertion } from '@/src/assertions/chatMessagesAssertion';
import { ConfirmationDialogAssertion } from '@/src/assertions/confirmationDialogAssertion';
import { ErrorToastAssertion } from '@/src/assertions/errorToastAssertion';
import { FolderAssertion } from '@/src/assertions/folderAssertion';
import { FooterAssertion } from '@/src/assertions/footerAssertion';
import { MenuAssertion } from '@/src/assertions/menuAssertion';
import { SendMessageAssertion } from '@/src/assertions/sendMessageAssertion';
import { SettingsModalAssertion } from '@/src/assertions/settingsModalAssertion';
Expand Down Expand Up @@ -196,6 +197,7 @@ const dialTest = test.extend<
sendMessageAssertion: SendMessageAssertion;
chatHeaderAssertion: ChatHeaderAssertion;
chatMessagesAssertion: ChatMessagesAssertion;
footerAssertion: FooterAssertion;
}
>({
// eslint-disable-next-line no-empty-pattern
Expand Down Expand Up @@ -670,6 +672,10 @@ const dialTest = test.extend<
const chatMessagesAssertion = new ChatMessagesAssertion(chatMessages);
await use(chatMessagesAssertion);
},
footerAssertion: async ({ chat }, use) => {
const footerAssertion = new FooterAssertion(chat.getFooter());
await use(footerAssertion);
},
});

export default dialTest;
5 changes: 2 additions & 3 deletions apps/chat-e2e/src/hooks/global-setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ResultFolder } from '@/src/testData';
import { FileUtil } from '@/src/utils';
import type { FullConfig } from '@playwright/test';
import path from 'path';

export const isApiStorageType =
Expand All @@ -26,8 +25,8 @@ export const ExecutionResults = {
testResultsPath: path.resolve(__dirname, `../../${ResultFolder.testResults}`),
};

async function globalSetup(config: FullConfig) {
if (config.projects[0].name === 'auth') {
async function globalSetup() {
if (process.env.NX_TASK_TARGET_TARGET === 'e2e:chat') {
for (const path of Object.values(ExecutionResults)) {
FileUtil.deleteFolder(path);
}
Expand Down
47 changes: 47 additions & 0 deletions apps/chat-e2e/src/testData/conversationHistory/conversationData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,53 @@ export class ConversationData extends FolderData {
.build();
}

public prepareConversationWithStagesInResponse(
model: DialAIEntityModel | string,
stagesCount: number,
) {
const modelToUse = { id: typeof model === 'string' ? model : model.id };
const conversation = this.conversationBuilder.getConversation();
const settings = {
prompt: conversation.prompt,
temperature: conversation.temperature,
selectedAddons: conversation.selectedAddons,
};
const userMessage: Message = {
role: Role.User,
content: 'stages request',
model: modelToUse,
settings: settings,
};

const stages: Stage[] = [];
for (let i = 0; i < stagesCount; i++) {
const stage: Stage = {
index: i,
name: `stage ${i}`,
status: 'completed',
content: 'stage content',
};
stages.push(stage);
}
const assistantMessage: Message = {
role: Role.Assistant,
content: 'response with stages',
model: modelToUse,
custom_content: {
stages: stages,
},
settings: settings,
};
const name = GeneratorUtil.randomString(10);
return this.conversationBuilder
.withId(`${modelToUse.id}${ItemUtil.conversationIdSeparator}${name}`)
.withName(name)
.withMessage(userMessage)
.withMessage(assistantMessage)
.withModel(modelToUse)
.build();
}

public getAttachmentData(attachmentUrl: string) {
const filename = FileApiHelper.extractFilename(attachmentUrl);
return {
Expand Down
7 changes: 7 additions & 0 deletions apps/chat-e2e/src/testData/expectedConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ export const ExpectedConstants = {
unselectAllTooltip: 'Unselect all',
deleteSelectedConversationsTooltip: 'Delete selected conversations',
deleteSelectedPromptsTooltip: 'Delete selected prompts',
promptLimitExceededTitle: 'Prompt limit exceeded',
promptLimitExceededMessage: (
maxPromptTokens: number,
enteredTokens: number,
remainedTokes: number,
) =>
`Prompt limit is ${maxPromptTokens} tokens. You have entered ${enteredTokens} tokens and are trying to select a prompt with more than ${remainedTokes} tokens. 1 token approximately equals to 4 characters.`,
};

export enum Groups {
Expand Down
5 changes: 5 additions & 0 deletions apps/chat-e2e/src/testData/expectedMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export enum ExpectedMessages {
addonIconIsValid = 'Addon icon is valid',
draggableAreaColorIsValid = 'Draggable area background color is valid',
folderNameColorIsValid = 'Folder name color is valid',
modalDialogTitleIsValid = 'Modal dialog title is valid',
confirmationMessageIsValid = 'Confirmation dialog message is valid',
chronologyMessageCountIsCorrect = 'Chat bar chronology messages count is correct',
fieldIsRequired = 'Field is required',
Expand Down Expand Up @@ -314,7 +315,11 @@ export enum ExpectedMessages {
featureIsToggledOff = 'Feature is toggled-off',
featureIsToggledOn = 'Feature is toggled-on',
elementColorIsValid = 'Element color is valid',
elementsCountIsValid = 'Elements count is valid',
menuIsVisible = 'Menu is visible',
menuIsNotVisible = 'Menu is not visible',
elementWidthIsValid = 'Element width is valid',
footerIsVisible = 'Footer is visible',
footerIsNotVisible = 'Footer is not visible',
footerContentIsNotEmpty = 'Footer content is not empty',
}
2 changes: 2 additions & 0 deletions apps/chat-e2e/src/testData/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export interface TreeEntity {
export type ElementState = 'visible' | 'hidden';

export type ElementCaretState = 'expanded' | 'collapsed';

export type ElementLabel = 'more' | 'less';
85 changes: 85 additions & 0 deletions apps/chat-e2e/src/tests/conversationWithStage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Conversation } from '@/chat/types/chat';
import dialTest from '@/src/core/dialFixtures';
import { Colors } from '@/src/ui/domData';
import { ModelsUtil } from '@/src/utils';

dialTest(
'Show more/less hides stages after 3rd',
async ({
dialHomePage,
conversationData,
localStorageManager,
dataInjector,
setTestIds,
chatMessages,
chatMessagesAssertion,
}) => {
setTestIds('EPMRTC-1757');
let conversation: Conversation;
const stagesCount = 5;
const maxDisplayedStagesCount = 3;

await dialTest.step(
'Prepare conversation with 3+ stages in response',
async () => {
conversation = conversationData.prepareConversationWithStagesInResponse(
ModelsUtil.getDefaultModel()!,
stagesCount,
);
await dataInjector.createConversations([conversation]);
await localStorageManager.setSelectedConversation(conversation);
},
);

await dialTest.step(
'Open conversation, verify first 3 stages are displayed, other are hidden under "Show more" blue button',
async () => {
await dialHomePage.openHomePage();
await dialHomePage.waitForPageLoaded();
await chatMessagesAssertion.assertMessageStagesCount(
2,
maxDisplayedStagesCount,
);
await chatMessagesAssertion.assertShowMoreLessButtonState(
'more',
'visible',
);
await chatMessagesAssertion.assertShowMoreLessButtonColor(
'more',
Colors.controlsBackgroundAccent,
);
},
);

await dialTest.step(
'Click on "Show more" and verify all stages and "Show less" button are displayed',
async () => {
await chatMessages.showMoreButton.click();
await chatMessagesAssertion.assertMessageStagesCount(2, stagesCount);
await chatMessagesAssertion.assertShowMoreLessButtonState(
'less',
'visible',
);
await chatMessagesAssertion.assertShowMoreLessButtonColor(
'less',
Colors.controlsBackgroundAccent,
);
},
);

await dialTest.step(
'Click on "Show less" and verify 3 stages and "Show more" button are displayed',
async () => {
await chatMessages.showLessButton.click();
await chatMessagesAssertion.assertMessageStagesCount(
2,
maxDisplayedStagesCount,
);
await chatMessagesAssertion.assertShowMoreLessButtonState(
'more',
'visible',
);
},
);
},
);
32 changes: 32 additions & 0 deletions apps/chat-e2e/src/tests/footer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import dialTest from '@/src/core/dialFixtures';
import { ExpectedMessages } from '@/src/testData';
import { expect } from '@playwright/test';

dialTest(
'EPAM AI Dial leads to kb',
async ({ dialHomePage, chat, footerAssertion, setTestIds }) => {
setTestIds('EPMRTC-361');

await dialTest.step(
'Open app and verify footer with configured content is displayed',
async () => {
await dialHomePage.openHomePage();
await dialHomePage.waitForPageLoaded({
isNewConversationVisible: true,
});
await footerAssertion.assertFooterState('visible');
await footerAssertion.assertFooterContentLength();
},
);

await dialTest.step(
'Click on any footer link and verify it is opened in a new tab',
async () => {
const newPage = await dialHomePage.getNewPage(() =>
chat.getFooter().openFooterLink(),
);
expect.soft(newPage, ExpectedMessages.newPageIsOpened).toBeDefined();
},
);
},
);
4 changes: 2 additions & 2 deletions apps/chat-e2e/src/tests/replay.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ dialTest(
)
.toBeHidden();

await chat.footer.waitForState({ state: 'attached' });
await chat.getFooter().waitForState({ state: 'attached' });
},
);

Expand All @@ -823,7 +823,7 @@ dialTest(
)
.toBeHidden();

await chat.footer.waitForState({ state: 'attached' });
await chat.getFooter().waitForState({ state: 'attached' });
},
);
},
Expand Down
Loading

0 comments on commit 5cf5fd5

Please sign in to comment.