mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
ci: add e2e workflow, optimize client code for testing (#771)
* refactor(e2e): fix tests with latest changes, convert to TS, use test Ids * chore(EndpointMenu.jsx): add data-testid attribute to new-conversation-menu button * refactor(EndpointItem): add data-testid attr., convert to TS * refactor(e2e): remove unnecessary awaits and convert to TS * chore(playwright.config.local.ts): add absolute path to server index.js file chore(playwright.config.local.ts): add dotenv configuration chore(playwright.config.local.ts): change webServer command to use absolute path chore(playwright.config.local.ts): add NODE_ENV and process.env to webServer env chore(playwright.config.local.ts): remove unused import chore(login.spec.js): delete login.spec.js file * chore(.gitignore): add 'my.secrets' to the list of ignored files fix(Registration.tsx): add 'data-testid' attribute to the error message div fix(Registration.spec.tsx): comment out test case that calls 'registerUser.mutate' * chore(ConvoIcon.tsx): add data-testid attribute to svg element chore(messages.spec.ts): refactor conversation navigation logic * chore(playwright.config.ts): add support for absolute path to server index.js file feat(playwright.config.ts): add support for dotenv configuration feat(playwright.config.ts): set NODE_ENV to 'production' in webServer environment variables * chore(workflows): comment out push event and specify paths for pull_request event in backend-review.yml chore(workflows): comment out push event and specify paths for pull_request event in frontend-review.yml * chore(install.js): add check to skip install script in CI environment * chore: complete playwright workflow * chore(Landing.tsx): add data-testid attribute to landing title element chore(authenticate.ts): update selector to wait for landing title element by test id instead of text content * chore(playwright.yml): add step to upload screenshot artifact on failure fix(authenticate.ts): capture screenshot before waiting for landing title and increase timeout due to GH Actions load time * chore(playwright.yml): rename artifact name from 'screenshot' to 'login-screenshot' feat(LoginForm.tsx): add data-testid attribute to login button fix(authenticate.ts): change screenshot name to 'login-screenshot.png' and conditionally take screenshot only in CI environment * chore(playwright.yml): add CI environment variable and set it to true * chore(playwright.yml): update Playwright installation command chore(playwright.config.ts): update storageState path to use process.cwd() * fix(playwright.yml): update node version to 18 in setup-node action fix(playwright.yml): update actions/cache to v3 in Cache Node.js modules step fix(playwright.yml): update actions/cache to v3 in Cache Playwright installations step fix(authenticate.ts): change login button click to press 'Enter' on password input * chore(playwright.yml): update E2E_USER_EMAIL and E2E_USER_PASSWORD values for testing purposes chore(authenticate.ts): add console.dir to log user object for debugging * chore(playwright.yml): add step to upload storageState artifact The storageState artifact is now uploaded as part of the workflow. This artifact contains the state of the storage used during the end-to-end tests. It will be retained for 2 days. * chore(playwright.yml): comment out upload screenshot step chore(playwright.config.ts): change NODE_ENV to development chore(authenticate.ts): comment out screenshot related code * chore(playwright.config.ts): add SESSION_EXPIRY environment variable with value 86400000 * chore(playwright.yml): update environment variables in Playwright workflow fix(General.tsx): add data-testid attributes to clear conversations buttons test(messages.spec.ts): add setup and teardown steps for clearing conversations before and after tests * fix(messages.spec.ts): fix clearing conversations before and after message tests feat(messages.spec.ts): add beforeEach and afterEach hooks to create and close new page for each test * chore: remove storageStage upload artifact
This commit is contained in:
parent
cb3cf9b33e
commit
c6f5d5d65c
24 changed files with 272 additions and 169 deletions
99
e2e/specs/messages.spec.ts
Normal file
99
e2e/specs/messages.spec.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
import { expect, test } from '@playwright/test';
|
||||
import type { Response, Page } from '@playwright/test';
|
||||
|
||||
const basePath = 'http://localhost:3080/chat/';
|
||||
const initialUrl = `${basePath}new`;
|
||||
const endpoints = ['google', 'openAI', 'azureOpenAI', 'bingAI', 'chatGPTBrowser', 'gptPlugins'];
|
||||
|
||||
function isUUID(uuid: string) {
|
||||
const regex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
||||
return regex.test(uuid);
|
||||
}
|
||||
|
||||
async function clearConvos(page: Page) {
|
||||
await page.goto(initialUrl);
|
||||
await page.getByRole('button', { name: 'test' }).click();
|
||||
await page.getByText('Settings').click();
|
||||
await page.getByTestId('clear-convos-initial').click();
|
||||
await page.getByTestId('clear-convos-confirm').click();
|
||||
await page.waitForSelector('[data-testid="convo-icon"]', { state: 'detached' });
|
||||
await page.getByRole('button', { name: 'Close' }).click();
|
||||
}
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
console.log('🤖: clearing conversations before message tests.');
|
||||
const page = await browser.newPage();
|
||||
await clearConvos(page);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ browser }) => {
|
||||
console.log('🤖: clearing conversations after message tests.');
|
||||
const page = await browser.newPage();
|
||||
await clearConvos(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, page }) => {
|
||||
page = await browser.newPage();
|
||||
await page.goto(initialUrl);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.describe('Messaging suite', () => {
|
||||
test('textbox should be focused after receiving message & test expected navigation', async ({
|
||||
page,
|
||||
}) => {
|
||||
test.setTimeout(120000);
|
||||
const message = 'hi';
|
||||
const endpoint = endpoints[1];
|
||||
await page.goto(initialUrl);
|
||||
await page.locator('#new-conversation-menu').click();
|
||||
await page.locator(`#${endpoint}`).click();
|
||||
await page.locator('form').getByRole('textbox').click();
|
||||
await page.locator('form').getByRole('textbox').fill(message);
|
||||
|
||||
const responsePromise = [
|
||||
page.waitForResponse(async (response: Response) => {
|
||||
return response.url().includes(`/api/ask/${endpoint}`) && response.status() === 200;
|
||||
}),
|
||||
page.locator('form').getByRole('textbox').press('Enter'),
|
||||
];
|
||||
|
||||
const [response] = (await Promise.all(responsePromise)) as [Response];
|
||||
const responseBody = await response.body();
|
||||
const messageSuccess = responseBody.includes('"final":true');
|
||||
expect(messageSuccess).toBe(true);
|
||||
|
||||
// Check if textbox is focused
|
||||
await page.waitForTimeout(250);
|
||||
const isTextboxFocused = await page.evaluate(() => {
|
||||
return document.activeElement === document.querySelector('[data-testid="text-input"]');
|
||||
});
|
||||
expect(isTextboxFocused).toBeTruthy();
|
||||
const currentUrl = page.url();
|
||||
expect(currentUrl).toBe(initialUrl);
|
||||
|
||||
//cleanup the conversation
|
||||
await page.getByText('New chat', { exact: true }).click();
|
||||
expect(page.url()).toBe(initialUrl);
|
||||
|
||||
// Click on the first conversation
|
||||
await page.getByTestId('convo-icon').first().click({ timeout: 5000 });
|
||||
const finalUrl = page.url();
|
||||
const conversationId = finalUrl.split(basePath).pop() ?? '';
|
||||
expect(isUUID(conversationId)).toBeTruthy();
|
||||
});
|
||||
|
||||
// in this spec as we are testing post-message navigation, we are not testing the message response
|
||||
test('Page navigations', async ({ page }) => {
|
||||
await page.goto(initialUrl);
|
||||
await page.getByTestId('convo-icon').first().click({ timeout: 5000 });
|
||||
const currentUrl = page.url();
|
||||
const conversationId = currentUrl.split(basePath).pop() ?? '';
|
||||
expect(isUUID(conversationId)).toBeTruthy();
|
||||
await page.getByText('New chat', { exact: true }).click();
|
||||
expect(page.url()).toBe(initialUrl);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue