Skip to content
Open
Show file tree
Hide file tree
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
12 changes: 7 additions & 5 deletions README-NJ.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ for

### Running E2E tests

Our tests live in: ./nj/e2e/\* and they can be run on their own with the following command:
Our tests live in: `./nj/e2e/*` and they can be run on their own with the following command:

1. Build everything
- `$ npm run reinstall`
Expand Down Expand Up @@ -156,8 +156,7 @@ If either the template or the secret values have been updated, you can update th
1. Navigate to the Actions tab in the repo
2. Select "Render and upload env file"
3. Select "Run Workflow" and select your target environment
4. The workflow will get the environment-specific values from secrets, perform `envsubst`, upload the file to S3, and
redeploy the service.
4. The workflow will get the environment-specific values from secrets, perform `envsubst`, upload the file to S3, and redeploy the service.

#### Manually set release tag for prod (Rollback Strategy, DANGER)

Expand Down Expand Up @@ -200,5 +199,8 @@ Guardrail configs are managed per-environment through the AWS console. To manage

### Secrets Manager Connection String

The connection string for DocumentDB lives in AWS Secrets Manager under the name `ai-assistant/docdb/uri`. If the
DocumentDB secret is rotated, it must be updated here for LibreChat to maintain connection.
The connection string for DocumentDB lives in AWS Secrets Manager under the name `ai-assistant/docdb/uri`. If the DocumentDB secret is rotated, it must be updated here for LibreChat to maintain connection.

## Updating the New Updates widget

The purpose of this widget is surfacing new updates and changes to the user. Information can be updated in `client/src/nj/components/NewUpdatesWidget.tsx`, and the env var `VITE_DISPLAY_UPDATE_WIDGET` must be set to `true`.
120 changes: 120 additions & 0 deletions nj/e2e/chat.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { test, expect } from '@playwright/test';

// Overrides global authentication setup
test.use({ storageState: undefined });

const CONVO_START_RESPONSE = {
streamId: 'mocked-stream-id',
conversationId: 'mocked-conversation-id',
status: 'started',
};

const SSE_EVENTS = [
{
created: true,
message: {
sender: 'User',
text: 'Can you tell me a joke?',
},
},
{
event: 'on_message_delta',
data: {
id: 'step_mock',
delta: {
content: [
{
type: 'text',
text: 'Mocked response',
index: 0,
},
],
},
},
},
{
final: true,
responseMessage: {
sender: 'AWS Bedrock',
text: 'Mocked response',
content: [
{
type: 'text',
text: 'Mocked response',
},
],
},
},
];

// Join SSE events into one stream
const sseBody = SSE_EVENTS.map(
(event) => `event: message\ndata: ${JSON.stringify(event)}\n\n`,
).join('');

test('prompt submission', async ({ page }) => {
// Intercept and mock API responses
await page.route('**/api/agents/chat/bedrock', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(CONVO_START_RESPONSE),
});
});

await page.route('**/api/agents/chat/stream/**', async (route) => {
await route.fulfill({
status: 200,
contentType: 'text/event-stream',
headers: { 'Cache-Control': 'no-cache' },
body: sseBody,
});
});

// Login
await page.goto('http://localhost:3080/login');
const loginForm = page.locator('form[aria-label="Login form"]');
console.log('form', loginForm);
await expect(loginForm).toBeVisible();
await expect(loginForm).toBeAttached();

// console.log('form html', await loginForm.evaluate((el) => el.outerHTML));

// //debugging
// console.log('login form count', await loginForm.count());
// console.log('email form count', await loginForm.getByLabel('Email').count());
// console.log('pwd form count', await loginForm.getByLabel('Password').count());
// await expect(loginForm).toBeVisible({ timeout: 15000 });

// //debugging flow
// await expect(loginForm).toBeVisible({ timeout: 15000 });
// const emailInput = loginForm.getByLabel('Email');
// await expect(emailInput).toBeVisible({ timeout: 15000 });
// await emailInput.fill('e2e-test@test.local');
// await loginForm.getByLabel('Password').fill('Test123!@');
// await loginForm.getByRole('button', { name: 'Continue' }).click();

// adding re: debug, etc.
// const emailInput = loginForm.getByLabel('Email');
const emailInput = loginForm.locator('input[name="email"]');
await expect(emailInput).toBeVisible({ timeout: 15000 });
await emailInput.fill('e2e-test@test.local');

// original flow - commented out to debug
// await loginForm.getByLabel('Email').fill('e2e-test@test.local'); commenting out in place of the two preceding lines to debug
await loginForm.getByLabel('Password').fill('Test123!@');
await loginForm.getByRole('button', { name: 'Continue' }).click();

await expect(page).toHaveURL(/c\/new/);
await page.goto('http://localhost:3080/c/new', { timeout: 10000 });

// Submit a prompt
const inputField = page.getByLabel('Message input');
await expect(inputField).toBeVisible({ timeout: 10000 });
await inputField.fill('Can you tell me a joke?');
await inputField.press('Enter');
await expect(page.getByText('Can you tell me a joke?')).toBeVisible();

// Wait for mocked response
await expect(page.getByText('Mocked response')).toBeVisible({ timeout: 10000 });
});
1 change: 1 addition & 0 deletions nj/nj.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,4 @@ ANALYTICS_GTM_ID=$ANALYTICS_GTM_ID
INTERFACE_AGENTS=$INTERFACE_AGENTS
INTERFACE_FILE_SEARCH=$INTERFACE_FILE_SEARCH


4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@
"data/",
"client/",
"admin/",
"packages/"
"packages/",
"e2e/",
"nj/e2e/"
]
}
}
Loading