Unverified 提交 90f5ca33 authored 作者: wwwillchen-bot's avatar wwwillchen-bot 提交者: GitHub

Fix flaky e2e tests with better selectors and waits (#2498)

## Summary - Fix flaky e2e tests across 6 test files by adding proper awaits, better CSS class matching, accordion state checks, and explicit waits for UI elements - Key fixes: missing `await` on expect in delete_app, regex anchoring for favorite_app class matching, accordion expansion guards in git_collaboration, `pressSequentially` for mention trigger detection, and visibility waits in supabase_migrations ## Test plan - Run the full e2e test suite to verify the fixed tests pass reliably - Specifically verify: `delete_app`, `favorite_app`, `file_tree_search`, `git_collaboration`, `mention_files`, and `supabase_migrations` tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2498"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Stabilized flaky e2e tests by improving selectors and adding explicit waits. Reliability is improved across delete_app, favorite_app, file_tree_search, git_collaboration, mention_files, and supabase_migrations. - **Bug Fixes** - Added missing await for visibility assertion in delete_app. - Anchored favorite star class regex to avoid matching hover:fill. - Updated file_tree_search to expect main.tsx. - Guarded Git Collaboration flows by checking accordion expansion and element visibility; standardized on Timeout.MEDIUM. - Used pressSequentially and waits for @ mention menu; verified Supabase migrations switch with toBeChecked() after visibility. <sup>Written for commit a28a3d981e049c023f3a5343ae57b813961a6680. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWill Chen <willchen90@gmail.com> Co-authored-by: 's avatarClaude Opus 4.5 <noreply@anthropic.com>
上级 633baeff
......@@ -23,5 +23,5 @@ testSkipIfWindows("delete app", async ({ po }) => {
// Make sure the app is deleted
await po.isCurrentAppNameNone();
expect(fs.existsSync(appPath)).toBe(false);
expect(po.getAppListItem({ appName })).not.toBeVisible();
await expect(po.getAppListItem({ appName })).not.toBeVisible();
});
......@@ -29,7 +29,7 @@ test.describe("Favorite App Tests", () => {
// Check that the star is filled (favorited)
const star = favoriteButton.locator("svg");
await expect(star).toHaveClass(/fill-\[#6c55dc\]/);
await expect(star).toHaveClass(/(?:^|\s)fill-\[#6c55dc\]/);
});
test("Remove app from favorite", async ({ po }) => {
......@@ -57,7 +57,7 @@ test.describe("Favorite App Tests", () => {
// Check that the star is filled (favorited)
const star = favoriteButton.locator("svg");
await expect(star).toHaveClass(/fill-\[#6c55dc\]/);
await expect(star).toHaveClass(/(?:^|\s)fill-\[#6c55dc\]/);
// Now, remove from favorite
const unfavoriteButton = appItem
......@@ -67,6 +67,7 @@ test.describe("Favorite App Tests", () => {
await unfavoriteButton.click();
// Check that the star is not filled (unfavorited)
await expect(star).not.toHaveClass(/fill-\[#6c55dc\]/);
// Match fill-[#6c55dc] only at start or after whitespace (not as part of hover:fill-...)
await expect(star).not.toHaveClass(/(?:^|\s)fill-\[#6c55dc\]/);
});
});
......@@ -20,7 +20,7 @@ test("file tree search finds content matches and surfaces line numbers", async (
// Content search should find files whose contents match the query and show line info
await searchInput.fill("import");
const resultItem = po.page.getByText("App.tsx").first();
const resultItem = po.page.getByText("main.tsx").first();
await expect(resultItem).toBeVisible({ timeout: Timeout.MEDIUM });
// Files are collapsed by default in the new accordion UI, so we need to click to expand
......
......@@ -37,7 +37,7 @@ test.describe("Git Collaboration", () => {
await expect(
po.page.getByTestId("branch-actions-menu-trigger"),
).toBeVisible({
timeout: 10000,
timeout: Timeout.MEDIUM,
});
await po.page.getByTestId("branch-actions-menu-trigger").click();
await po.page.getByTestId("create-branch-trigger").click();
......@@ -93,9 +93,19 @@ test.describe("Git Collaboration", () => {
"main",
);
// Helper to ensure branch item is visible (expands accordion if needed)
async function ensureBranchItemVisible(branchName: string) {
const branchItem = po.page.getByTestId(`branch-item-${branchName}`);
if (!(await branchItem.isVisible().catch(() => false))) {
await branchesCard.click();
}
await expect(branchItem).toBeVisible({ timeout: Timeout.MEDIUM });
}
// Rename feature-2 to feature-2-renamed
const renamedBranch = "feature-2-renamed";
await branchesCard.click();
// Ensure the branches accordion is expanded (it may already be expanded, so check first)
await ensureBranchItemVisible(featureBranch2);
await po.page.getByTestId(`branch-actions-${featureBranch2}`).click();
await po.page.getByTestId("rename-branch-menu-item").click();
await po.page.getByTestId("rename-branch-input").fill(renamedBranch);
......@@ -147,7 +157,8 @@ test.describe("Git Collaboration", () => {
expect(fs.existsSync(mergeTestFilePath)).toBe(false);
// Merge feature-1 into main (we are currently on main)
await branchesCard.click();
// Ensure the branches accordion is expanded
await ensureBranchItemVisible(featureBranch);
await po.page.getByTestId(`branch-actions-${featureBranch}`).click();
await po.page.getByTestId("merge-branch-menu-item").click();
await po.page.getByTestId("merge-branch-submit-button").click();
......@@ -177,7 +188,8 @@ test.describe("Git Collaboration", () => {
// 5. Delete Branch
// Delete feature-1
await branchesCard.click();
// Ensure the branches accordion is expanded
await ensureBranchItemVisible(featureBranch);
await po.page.getByTestId(`branch-actions-${featureBranch}`).click();
await po.page.getByTestId("delete-branch-menu-item").click();
await po.page.getByRole("button", { name: "Delete Branch" }).click();
......@@ -230,7 +242,7 @@ test.describe("Git Collaboration", () => {
await expect(
po.page.getByTestId("branch-actions-menu-trigger"),
).toBeVisible({
timeout: 10000,
timeout: Timeout.MEDIUM,
});
// Test git pull - should succeed with no remote changes
......
import { test } from "./helpers/test_helper";
import { expect } from "@playwright/test";
import { test, Timeout } from "./helpers/test_helper";
test("mention file", async ({ po }) => {
await po.setUp({ autoApprove: true });
......@@ -6,8 +7,14 @@ test("mention file", async ({ po }) => {
await po.importApp("minimal-with-ai-rules");
await po.goToAppsTab();
await po.getChatInput().click();
await po.getChatInput().fill("[dump] @");
await po.page.getByRole("menuitem", { name: "Choose AI_RULES.md" }).click();
// Use pressSequentially so the mention trigger (@) is properly detected by Lexical
await po.getChatInput().pressSequentially("[dump] @");
// Wait for the mention menu to appear
const menuItem = po.page.getByRole("menuitem", {
name: "Choose AI_RULES.md",
});
await expect(menuItem).toBeVisible({ timeout: Timeout.MEDIUM });
await menuItem.click();
await po.page.getByRole("button", { name: "Send message" }).click();
await po.waitForChatCompletion();
......
import { expect } from "@playwright/test";
import { testSkipIfWindows } from "./helpers/test_helper";
import { testSkipIfWindows, Timeout } from "./helpers/test_helper";
import fs from "fs-extra";
import path from "path";
import { execSync } from "child_process";
......@@ -28,7 +28,10 @@ testSkipIfWindows("supabase migrations", async ({ po }) => {
const migrationsSwitch = po.page.getByRole("switch", {
name: "Write SQL migration files",
});
await expect(migrationsSwitch).toBeVisible({ timeout: Timeout.MEDIUM });
await migrationsSwitch.click();
// Wait for the setting to be persisted
await expect(migrationsSwitch).toBeChecked();
await po.goToChatTab();
// Send a prompt that triggers a migration
......@@ -91,7 +94,10 @@ testSkipIfWindows("supabase migrations with native git", async ({ po }) => {
const migrationsSwitch = po.page.getByRole("switch", {
name: "Write SQL migration files",
});
await expect(migrationsSwitch).toBeVisible({ timeout: Timeout.MEDIUM });
await migrationsSwitch.click();
// Wait for the setting to be persisted
await expect(migrationsSwitch).toBeChecked();
await po.goToChatTab();
// Send a prompt that triggers a migration
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论