• keppo-bot[bot]'s avatar
    Deflake sendPrompt E2E helper against Lexical/jotai chat-switch races (#3246) · f1cc6330
    keppo-bot[bot] 提交于
    ## Summary
    
    Fixes the 6 `TimeoutError: locator.click: ... element is not enabled`
    failures in `chat_tabs.spec.ts` and `per_chat_input.spec.ts` on CI run
    [24692456779](https://github.com/dyad-sh/dyad/actions/runs/24692456779)
    caused by a Lexical/jotai race during chat switches.
    
    ## Root cause
    
    Trace + screenshot from the failing shards show chat 2 with an empty
    input and a disabled Send button the moment the second `sendPrompt()`
    runs. The race:
    
    1. `clickNewChat()` navigates to chat 2 (`selectedChatIdAtom` flips, URL
    updates, `ChatInput` re-renders with `chatId=2`).
    2. Playwright's `fill()` into the Lexical editor fires
    `OnChangePlugin.onChange` before React has flushed the atom update for
    this render cycle.
    3. `chatInputValueAtom`'s writer is keyed off `selectedChatIdAtom`, so
    the typed text gets stored under the **previous** chat's slot.
    4. On the next render `ExternalValueSyncPlugin` sees `value=""` for chat
    2 and resets the editor to empty.
    5. `inputValue.trim()` is empty → Send button stays `disabled` → 30s
    click timeout.
    
    Only the *second* `sendPrompt()` after a `clickNewChat()` fails, and
    it's flaky because it depends on render/event ordering.
    
    ## Fix
    
    Wrap `click → fill` in `expect.toPass()` and assert the editor actually
    contains the prompt and the Send button is enabled before clicking. On a
    dropped fill the loop re-runs once atoms settle, eliminating the race
    deterministically. No product changes.
    
    ## Test plan
    
    - [x] `npm run fmt && npm run lint && npm run ts`
    - [ ] CI: chat_tabs.spec.ts and per_chat_input.spec.ts pass on shards
    1/2
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    <!-- devin-review-badge-begin -->
    
    ---
    
    <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/3246"
    target="_blank">
      <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 in Devin Review">
      </picture>
    </a>
    <!-- devin-review-badge-end -->
    Co-authored-by: 's avatarWill Chen <7344640+wwwillchen@users.noreply.github.com>
    Co-authored-by: 's avatarClaude Opus 4.7 (1M context) <noreply@anthropic.com>
    f1cc6330
名称
最后提交
最后更新
.agents 正在载入提交数据...
.claude 正在载入提交数据...
.cursor/rules 正在载入提交数据...
.devcontainer 正在载入提交数据...
.github 正在载入提交数据...
.husky 正在载入提交数据...
.storybook 正在载入提交数据...
assets 正在载入提交数据...
docs 正在载入提交数据...
drizzle 正在载入提交数据...
e2e-tests 正在载入提交数据...
makers 正在载入提交数据...
packages/@dyad-sh 正在载入提交数据...
plans 正在载入提交数据...
rules 正在载入提交数据...
scaffold 正在载入提交数据...
scripts 正在载入提交数据...
shared 正在载入提交数据...
src 正在载入提交数据...
testing 正在载入提交数据...
tools 正在载入提交数据...
worker 正在载入提交数据...
workers/tsc 正在载入提交数据...
.cursorignore 正在载入提交数据...
.env.example 正在载入提交数据...
.eslintrc.json 正在载入提交数据...
.gitattributes 正在载入提交数据...
.gitignore 正在载入提交数据...
.npmrc 正在载入提交数据...
.oxfmtrc.json 正在载入提交数据...
.oxlintrc.json 正在载入提交数据...
.prettierignore 正在载入提交数据...
.prettierrc 正在载入提交数据...
AGENTS.md 正在载入提交数据...
CLA.md 正在载入提交数据...
CLAUDE.md 正在载入提交数据...
CONTRIBUTING.md 正在载入提交数据...
LICENSE 正在载入提交数据...
README.md 正在载入提交数据...
SECURITY.md 正在载入提交数据...
biome.json 正在载入提交数据...
components.json 正在载入提交数据...
drizzle.config.ts 正在载入提交数据...
forge.config.ts 正在载入提交数据...
forge.env.d.ts 正在载入提交数据...
index.html 正在载入提交数据...
lint-staged.config.js 正在载入提交数据...
merge.config.ts 正在载入提交数据...
package-lock.json 正在载入提交数据...
package.json 正在载入提交数据...
playwright.config.ts 正在载入提交数据...
tsconfig.app.json 正在载入提交数据...
tsconfig.json 正在载入提交数据...
tsconfig.node.json 正在载入提交数据...
vite.main.config.mts 正在载入提交数据...
vite.preload.config.mts 正在载入提交数据...
vite.renderer.config.mts 正在载入提交数据...
vite.worker.config.mts 正在载入提交数据...
vitest.config.ts 正在载入提交数据...
windowsSign.ts 正在载入提交数据...