Loading...
Loading...
Write and maintain Playwright end-to-end tests for the Onyx application. Use when creating new E2E tests, debugging test failures, adding test coverage, or when the user mentions Playwright, E2E tests, or browser testing.
npx skill4agent add onyx-dot-app/onyx playwright-e2e-testsweb/tests/e2e/auth/admin/chat/assistants/connectors/mcp/web/playwright.config.tsweb/tests/e2e/utils/web/tests/e2e/constants.tsweb/tests/e2e/global-setup.tsweb/output/playwright/@tests/e2e/../../../web/tsconfig.jsonweb/tests/import { loginAs } from "@tests/e2e/utils/auth";
import { OnyxApiClient } from "@tests/e2e/utils/onyxApiClient";
import { TEST_ADMIN_CREDENTIALS } from "@tests/e2e/constants";.ts.js# Run a specific test file
npx playwright test web/tests/e2e/chat/default_assistant.spec.ts
# Run a specific project
npx playwright test --project admin
npx playwright test --project exclusive| Project | Description | Parallelism |
|---|---|---|
| Standard tests (excludes | Parallel |
| Serial, slower tests (tagged | 1 worker |
admin_auth.jsonglobal-setup.tsworker0@example.comworker7@example.comadmin_auth.jsonadmin2_auth.jsonworker{N}_auth.json"worker"storageState: "admin_auth.json"import { loginAs } from "@tests/e2e/utils/auth";
await page.context().clearCookies();
await loginAs(page, "admin2");
// Log in as the worker-specific user (preferred for test isolation):
import { loginAsWorkerUser } from "@tests/e2e/utils/auth";
await page.context().clearCookies();
await loginAsWorkerUser(page, testInfo.workerIndex);import { test, expect } from "@playwright/test";
test.describe("Feature Name", () => {
test("should describe expected behavior clearly", async ({ page }) => {
await page.goto("/app");
await page.waitForLoadState("networkidle");
// Already authenticated as admin — go straight to testing
});
});afterAllworker0@example.comworker7@example.comloginAsWorkerUsertestInfo.workerIndeximport { test } from "@playwright/test";
import { loginAsWorkerUser } from "@tests/e2e/utils/auth";
test.beforeEach(async ({ page }, testInfo) => {
await page.context().clearCookies();
await loginAsWorkerUser(page, testInfo.workerIndex);
});"admin2""admin""admin"chat/default_assistant.spec.tsloginAsRandomUserbeforeAllafterAllOnyxApiClientchat/default_assistant.spec.tsmcp/mcp_oauth_flow.spec.tsOnyxApiClient@tests/e2e/utils/onyxApiClientcreateFileConnector()deleteCCPair()pauseConnector()ensurePublicProvider()createRestrictedProvider()setProviderAsDefault()createAssistant()deleteAssistant()findAssistantByName()createUserGroup()deleteUserGroup()setUserRole()createWebSearchProvider()createImageGenerationConfig()createChatSession()deleteChatSession()chatActions@tests/e2e/utils/chatActionssendMessage(page, message)startNewChat(page)verifyDefaultAssistantIsChosen(page)verifyAssistantIsChosen(page, name)switchModel(page, modelName)visualRegression@tests/e2e/utils/visualRegressionexpectScreenshot(page, { name, mask?, hide?, fullPage? })expectElementScreenshot(locator, { name, mask?, hide? })VISUAL_REGRESSION=truetheme@tests/e2e/utils/themeTHEMES["light", "dark"] as constsetThemeBeforeNavigation(page, theme)next-themeslocalStorageTHEMEStest.describesetThemeBeforeNavigationbeforeEachpage.goto()admin/admin_pages.spec.tschat/chat_message_rendering.spec.tsimport { THEMES, setThemeBeforeNavigation } from "@tests/e2e/utils/theme";
for (const theme of THEMES) {
test.describe(`Feature (${theme} mode)`, () => {
test.beforeEach(async ({ page }) => {
await setThemeBeforeNavigation(page, theme);
});
test("renders correctly", async ({ page }) => {
await page.goto("/app");
await expectScreenshot(page, { name: `feature-${theme}` });
});
});
}tools@tests/e2e/utils/toolsTOOL_IDSdata-testidopenActionManagement(page)data-testidaria-labelpage.getByTestId("AppSidebar/new-session")
page.getByLabel("admin-page-title")page.getByRole("button", { name: "Create" })
page.getByRole("dialog")page.getByText("Custom Assistant")
page.getByLabel("Email")page.locator('input[name="name"]')
page.locator("#onyx-chat-input-textarea")page.locator// Visibility
await expect(page.getByTestId("onyx-logo")).toBeVisible({ timeout: 5000 });
// Text content
await expect(page.getByTestId("assistant-name-display")).toHaveText("My Assistant");
// Count
await expect(page.locator('[data-testid="onyx-ai-message"]')).toHaveCount(2, { timeout: 30000 });
// URL
await expect(page).toHaveURL(/chatId=/);
// Element state
await expect(toggle).toBeChecked();
await expect(button).toBeEnabled();assertpage.waitForTimeout()// Wait for load state after navigation
await page.goto("/app");
await page.waitForLoadState("networkidle");
// Wait for specific element
await page.getByTestId("chat-intro").waitFor({ state: "visible", timeout: 10000 });
// Wait for URL change
await page.waitForFunction(() => window.location.href.includes("chatId="), null, { timeout: 10000 });
// Wait for network response
await page.waitForResponse(resp => resp.url().includes("/api/chat") && resp.status() === 200);"should display greeting message when opening new chat"OnyxApiClientloginAsWorkerUser(page, testInfo.workerIndex)afterAllloginAsRandomUserutils/waitForwaitForLoadState"E2E-CMD Chat 1"afterAll\@exclusiveexpectScreenshot()