Skip to content

Wegent/fix settings model e2e tests#742

Open
joyway1978 wants to merge 9 commits intowecode-ai:mainfrom
joyway1978:wegent/fix-settings-model-e2e-tests
Open

Wegent/fix settings model e2e tests#742
joyway1978 wants to merge 9 commits intowecode-ai:mainfrom
joyway1978:wegent/fix-settings-model-e2e-tests

Conversation

@joyway1978
Copy link
Copy Markdown
Collaborator

@joyway1978 joyway1978 commented Mar 13, 2026

Wegent/fix settings model e2e tests

Summary by CodeRabbit

Release Notes

  • Tests

    • Enhanced end-to-end test reliability for model management, chat workflows, and settings with improved element detection and stability measures.
    • Strengthened test coverage for image browser interactions and clarification flows.
  • Chores

    • Added development utility script for port occupancy management.

zhongwei9 and others added 9 commits March 12, 2026 11:24
- Add data-testid to QuickAccessCards team cards
- Update chat-flow.spec.ts to select model (公网:GLM-5)
- Use data-testid for send button consistently
- Simplify QuickAccessCards selection logic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add data-testid support to ActionButton component
- Add data-testid="clarification-toggle" to ClarificationToggle
- Update chat-flow.spec.ts to use data-testid for finding clarification button
- Simplify detection logic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add data-testid to MessagesArea container
- Add data-testid to ClarificationForm and its elements
- Add data-testid to ClarificationQuestion radio/checkbox options
- Add data-testid to AI message icon (Bot icon)
- Add data-testid to ChatInputControls
- Add data-testid to QuickAccessCards container
- Update chat-flow.spec.ts to use data-testid exclusively

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Support both English and Chinese titles in settings-model.spec.ts
- Update selectTestModel to use data-testid and handle all button states
- Fix button text matching to include '选择模型' (Select Model)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix settings-model.spec.ts title selector to use 'Model Management' / '模型管理'

- Add data-testid to model-id-name-input in ModelEditDialog

- Update chat-image-browser-e2e.spec.ts selectTestModel with better detection

- Increase timeouts and add error state detection
- settings-model.spec.ts:
  - Change waitUntil from 'domcontentloaded' to 'networkidle'
  - Add wait for settings content area to be visible
  - Add retry logic for flaky title loading
  - Add wait for dialog to open before checking form elements
  - Increase timeouts for form element visibility

- chat-image-browser-e2e.spec.ts:
  - Add dismissOnboardingTour() calls before clicking elements
  - Fix driver-overlay blocking clicks in Strategy 2, 3, and 4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
settings-model.spec.ts:
- Fix model creation test by targeting Model ID dropdown instead of provider dropdown
- Use more specific selectors to avoid clicking wrong elements in dialog

chat-image-browser-e2e.spec.ts:
- Enhance dismissOnboardingTour() to forcefully remove driver.js elements from DOM
- Increase wait time for model dropdown options to load (2s instead of 1s)
- Filter out input elements when selecting model options

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix the failing e2e tests in settings-model.spec.ts:

1. Change wait strategy from 'networkidle' to 'domcontentloaded' to avoid
   timeout issues with ongoing network requests
2. Add explicit wait for model management title in beforeEach to ensure
   page is fully loaded before tests run
3. Increase dialog open timeout from 1000ms to 1500ms for better reliability
4. Increase element visibility timeouts from 10000ms to 15000ms
5. Remove redundant title checks in individual tests (already done in beforeEach)
6. Update visual regression test to wait for title instead of fixed timeout

These changes improve test reliability by:
- Using more reliable page load detection
- Ensuring elements are visible before interacting with them
- Providing adequate time for dialog animations to complete

Refs: CI e2e test failures in settings-model.spec.ts
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

This pull request introduces data-testid attributes across frontend components and E2E tests to improve test reliability, updates E2E tests to use these new selectors instead of legacy ones, and refactors dialog-based UI handling in model management tests. Additionally, a port management utility script is added.

Changes

Cohort / File(s) Summary
E2E Test Refactoring for Dialog-Based UI
frontend/e2e/tests/settings-model.spec.ts, frontend/e2e/tests/visual/settings-visual.spec.ts
Updated model edit flow from full-page form to dialog form with explicit waits for dialog appearance, visibility, and closure; replaced navigation-based waits with dialog-specific timeouts and refined element selectors using data-testid attributes.
E2E Chat & Onboarding Improvements
frontend/e2e/tests/tasks/chat-image-browser-e2e.spec.ts, tests/specs/chat-flow.spec.ts
Introduced proactive DOM cleanup for driver.js onboarding elements, strengthened overlay dismissal logic, improved model selector flow with data-testid preference and fallback paths, and migrated all selectors to data-testid-based approach for robustness across UI changes.
Component Test Attribute Additions
frontend/src/components/ui/action-button.tsx, frontend/src/features/settings/components/ModelEditDialog.tsx, frontend/src/features/tasks/components/chat/QuickAccessCards.tsx, frontend/src/features/tasks/components/clarification/*, frontend/src/features/tasks/components/input/ChatInputControls.tsx, frontend/src/features/tasks/components/message/*
Added data-testid attributes to ActionButton, model ID input, quick-access cards, clarification form elements (ClarificationForm, ClarificationQuestion, ClarificationToggle), chat input controls, and message components (MessageBubble, MessagesArea) for improved test targeting without behavioral changes.
Support Utilities
stop_port.sh
Added new Bash script for port occupancy detection, user confirmation-based process termination, and post-action verification for ports 8000, 8100, and 8001.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • Micro66
  • feifei325

Poem

🐰 Hop, hop, test IDs bloom in every place,
Data-testid marks the testing race,
From buttons bright to messages clear,
Dialogs dance and selectors appear,
Onboarding waves and ports take flight,
E2E tests now shine so bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically addresses the main purpose of the PR: fixing end-to-end tests for the settings model component with improvements to selectors, waits, and dialog handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
stop_port.sh (1)

35-39: Prefer graceful termination before forcing SIGKILL.

Line 38 uses unconditional kill -9. A TERM-first approach is safer and still clears stuck processes when needed.

🔧 Proposed safer termination flow
-        kill -9 $PIDS
+        kill $PIDS 2>/dev/null
+        sleep 1
+        REMAINING_PIDS=$(lsof -ti ":$port")
+        if [ -n "$REMAINING_PIDS" ]; then
+            kill -9 $REMAINING_PIDS
+        fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stop_port.sh` around lines 35 - 39, The script stop_port.sh currently sends
unconditional SIGKILL to PIDS (variable PIDS) which is unsafe; change the
termination flow in the block that finds PIDS=$(lsof -ti ":$port") to send
SIGTERM first (kill -TERM $PIDS), wait a short interval and re-check whether
those PIDs still exist, and only then send SIGKILL (kill -9 $PIDS) for any
remaining live PIDs; ensure you properly quote/iterate the PIDS variable when
calling kill and use a small retry/wait loop (check with ps or lsof) so the code
in the if [ -n "$PIDS" ]; then branch gracefully terminates before forcing kill.
frontend/e2e/tests/settings-model.spec.ts (1)

48-56: Consider removing the fixed waitForTimeout(1500) before checking dialog visibility.

The 1.5-second delay before checking for the dialog is arbitrary. The subsequent waitForSelector with a 15-second timeout should be sufficient to wait for the dialog to appear.

♻️ Proposed simplification
     await createButton.first().click()
 
-    // Wait for dialog to open (animation + rendering time)
-    await page.waitForTimeout(1500)
-
     // Wait for dialog content to be visible
     await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 15000 })
 
     // Model edit is a dialog form - check for the model ID input
     const modelIdInput = page.locator('[data-testid="model-id-name-input"]')
     await expect(modelIdInput).toBeVisible({ timeout: 15000 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/e2e/tests/settings-model.spec.ts` around lines 48 - 56, Remove the
fixed 1.5s delay by deleting the call to page.waitForTimeout(1500) and rely on
the existing await page.waitForSelector('[role="dialog"]', { state: 'visible',
timeout: 15000 }) (and the subsequent locator checks like const modelIdInput =
page.locator('[data-testid="model-id-name-input"]')) to wait for the dialog to
appear; this removes the arbitrary pause and keeps the test deterministic using
the selector timeouts.
tests/specs/chat-flow.spec.ts (1)

171-177: Fragile check for enabled state relies on CSS class name.

Checking buttonClass?.includes('primary') to verify enabled state is brittle—it will break if the styling changes. Consider using a more explicit indicator.

♻️ Proposed alternative: Check aria-pressed or data attribute

If the component supports it, prefer checking aria-pressed="true" or a data-active attribute rather than CSS class names:

     // Verify the button is now in enabled state (has primary/border-primary class)
-    const buttonClass = await clarificationToggle.getAttribute('class')
-    const isEnabled = buttonClass?.includes('primary')
+    // Check if button indicates active state via aria or styling
+    const isEnabled = await clarificationToggle.evaluate((el) => {
+      return el.getAttribute('aria-pressed') === 'true' || 
+             el.classList.contains('border-primary') ||
+             el.classList.contains('bg-primary')
+    })

Alternatively, add a data-testid or data-active attribute to the component for explicit state indication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/specs/chat-flow.spec.ts` around lines 171 - 177, The check using
buttonClass?.includes('primary') is brittle; update the enabled-state detection
for the clarificationToggle element to use an explicit attribute instead (e.g.,
check clarificationToggle.getAttribute('aria-pressed') === 'true' or
clarificationToggle.getAttribute('data-active') === 'true'), falling back to the
class check only if those attributes are absent; adjust the conditional that
calls test.skip() and the console message to reflect the new attribute-based
check so the test reliably detects the toggle state.
frontend/e2e/tests/tasks/chat-image-browser-e2e.spec.ts (1)

257-266: Redundant style assignment before element removal.

Setting style.display = 'none' is unnecessary since remove() immediately deletes the element from the DOM.

♻️ Proposed simplification
         console.warn('Overlay still visible, forcefully removing from DOM')
         await page.evaluate(() => {
           document.querySelectorAll('.driver-overlay, .driver-popover, .driver-popover-tip, [class*="driver-"]').forEach(el => {
-            ;(el as HTMLElement).style.display = 'none'
             el.remove()
           })
         })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/e2e/tests/tasks/chat-image-browser-e2e.spec.ts` around lines 257 -
266, The code inside the recovery block for driverOverlay redundantly sets (el
as HTMLElement).style.display = 'none' immediately before el.remove(); update
the cleanup in the driverOverlay.isVisible check to simply remove matched
elements without changing their style: locate the driverOverlay handling (use
symbols driverOverlay, isVisible, page.evaluate and the selector
'.driver-overlay, .driver-popover, .driver-popover-tip, [class*="driver-"]') and
delete the style assignment so the evaluation only calls el.remove() for each
element, keeping the waitForTimeout(500) afterwards.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/e2e/tests/settings-model.spec.ts`:
- Around line 99-106: After clicking the submitButton in the test, replace the
blind wait with an explicit assertion that verifies the dialog actually closed
or a success notification appeared: wait for the ModelEditDialog to be
detached/hidden (use the dialog's root selector or the same locator used to open
it) or wait for the success toast/toast text that your app emits on successful
save, since ModelEditDialog calls onClose() only on success; update the test
around submitButton.click() to await that dialog-closed or success-toast
condition instead of page.waitForTimeout(2000).

In `@frontend/src/features/tasks/components/chat/QuickAccessCards.tsx`:
- Around line 221-223: The data-testid on the team card (in
QuickAccessCards.tsx) is currently using the mutable team.name which can change
and cause flaky selectors; update the test id to use a stable, immutable
identifier (e.g., team.id or team.teamId) instead of team.name in the element
where onClick={() => !isClicked && handleTeamClick(team)} is defined, and adjust
any tests that assert against the old `quick-access-team-{team.name}` string to
use the new `quick-access-team-{team.id}` format.

---

Nitpick comments:
In `@frontend/e2e/tests/settings-model.spec.ts`:
- Around line 48-56: Remove the fixed 1.5s delay by deleting the call to
page.waitForTimeout(1500) and rely on the existing await
page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 15000 })
(and the subsequent locator checks like const modelIdInput =
page.locator('[data-testid="model-id-name-input"]')) to wait for the dialog to
appear; this removes the arbitrary pause and keeps the test deterministic using
the selector timeouts.

In `@frontend/e2e/tests/tasks/chat-image-browser-e2e.spec.ts`:
- Around line 257-266: The code inside the recovery block for driverOverlay
redundantly sets (el as HTMLElement).style.display = 'none' immediately before
el.remove(); update the cleanup in the driverOverlay.isVisible check to simply
remove matched elements without changing their style: locate the driverOverlay
handling (use symbols driverOverlay, isVisible, page.evaluate and the selector
'.driver-overlay, .driver-popover, .driver-popover-tip, [class*="driver-"]') and
delete the style assignment so the evaluation only calls el.remove() for each
element, keeping the waitForTimeout(500) afterwards.

In `@stop_port.sh`:
- Around line 35-39: The script stop_port.sh currently sends unconditional
SIGKILL to PIDS (variable PIDS) which is unsafe; change the termination flow in
the block that finds PIDS=$(lsof -ti ":$port") to send SIGTERM first (kill -TERM
$PIDS), wait a short interval and re-check whether those PIDs still exist, and
only then send SIGKILL (kill -9 $PIDS) for any remaining live PIDs; ensure you
properly quote/iterate the PIDS variable when calling kill and use a small
retry/wait loop (check with ps or lsof) so the code in the if [ -n "$PIDS" ];
then branch gracefully terminates before forcing kill.

In `@tests/specs/chat-flow.spec.ts`:
- Around line 171-177: The check using buttonClass?.includes('primary') is
brittle; update the enabled-state detection for the clarificationToggle element
to use an explicit attribute instead (e.g., check
clarificationToggle.getAttribute('aria-pressed') === 'true' or
clarificationToggle.getAttribute('data-active') === 'true'), falling back to the
class check only if those attributes are absent; adjust the conditional that
calls test.skip() and the console message to reflect the new attribute-based
check so the test reliably detects the toggle state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 68e9fb0e-424f-47bf-b0e3-bdb19c48684e

📥 Commits

Reviewing files that changed from the base of the PR and between 57562f0 and c0c3baf.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • frontend/e2e/tests/settings-model.spec.ts
  • frontend/e2e/tests/tasks/chat-image-browser-e2e.spec.ts
  • frontend/e2e/tests/visual/settings-visual.spec.ts
  • frontend/src/components/ui/action-button.tsx
  • frontend/src/features/settings/components/ModelEditDialog.tsx
  • frontend/src/features/tasks/components/chat/QuickAccessCards.tsx
  • frontend/src/features/tasks/components/clarification/ClarificationForm.tsx
  • frontend/src/features/tasks/components/clarification/ClarificationQuestion.tsx
  • frontend/src/features/tasks/components/clarification/ClarificationToggle.tsx
  • frontend/src/features/tasks/components/input/ChatInputControls.tsx
  • frontend/src/features/tasks/components/message/MessageBubble.tsx
  • frontend/src/features/tasks/components/message/MessagesArea.tsx
  • stop_port.sh
  • tests/specs/chat-flow.spec.ts

Comment on lines 99 to 106
// Submit form
const submitButton = page.locator('button:has-text("Save"), button:has-text("保存")').first()
if (await submitButton.isVisible({ timeout: 3000 }).catch(() => false)) {
if (await submitButton.isVisible({ timeout: 5000 }).catch(() => false)) {
await submitButton.click()

// Wait for navigation back to list or validation error
await page.waitForURL(/\/settings/, { timeout: 10000 }).catch(() => {
// May stay on form with validation errors
})
// Wait for dialog to close or validation error
await page.waitForTimeout(2000)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test doesn't verify save success or failure.

After clicking submit, the test waits 2 seconds and ends without verifying the dialog closed or a success toast appeared. Per the context snippet from ModelEditDialog.tsx, onClose() is only called on success.

🔧 Proposed fix to verify dialog closure
     const submitButton = page.locator('button:has-text("Save"), button:has-text("保存")').first()
     if (await submitButton.isVisible({ timeout: 5000 }).catch(() => false)) {
       await submitButton.click()
 
-      // Wait for dialog to close or validation error
-      await page.waitForTimeout(2000)
+      // Verify dialog closes on success (or remains open on validation error)
+      const dialogClosed = await page.locator('[role="dialog"]').isHidden({ timeout: 5000 }).catch(() => false)
+      if (!dialogClosed) {
+        console.log('Dialog still visible - may have validation errors')
+      }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Submit form
const submitButton = page.locator('button:has-text("Save"), button:has-text("保存")').first()
if (await submitButton.isVisible({ timeout: 3000 }).catch(() => false)) {
if (await submitButton.isVisible({ timeout: 5000 }).catch(() => false)) {
await submitButton.click()
// Wait for navigation back to list or validation error
await page.waitForURL(/\/settings/, { timeout: 10000 }).catch(() => {
// May stay on form with validation errors
})
// Wait for dialog to close or validation error
await page.waitForTimeout(2000)
}
// Submit form
const submitButton = page.locator('button:has-text("Save"), button:has-text("保存")').first()
if (await submitButton.isVisible({ timeout: 5000 }).catch(() => false)) {
await submitButton.click()
// Verify dialog closes on success (or remains open on validation error)
const dialogClosed = await page.locator('[role="dialog"]').isHidden({ timeout: 5000 }).catch(() => false)
if (!dialogClosed) {
console.log('Dialog still visible - may have validation errors')
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/e2e/tests/settings-model.spec.ts` around lines 99 - 106, After
clicking the submitButton in the test, replace the blind wait with an explicit
assertion that verifies the dialog actually closed or a success notification
appeared: wait for the ModelEditDialog to be detached/hidden (use the dialog's
root selector or the same locator used to open it) or wait for the success
toast/toast text that your app emits on successful save, since ModelEditDialog
calls onClose() only on success; update the test around submitButton.click() to
await that dialog-closed or success-toast condition instead of
page.waitForTimeout(2000).

Comment on lines 221 to 223
onClick={() => !isClicked && handleTeamClick(team)}
data-testid={`quick-access-team-${team.name}`}
className={`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use a stable key for team-card test IDs.

Line 222 uses team.name in data-testid, which can be duplicated/renamed and make selectors flaky. Prefer an immutable ID.

🔧 Proposed fix
-        data-testid={`quick-access-team-${team.name}`}
+        data-testid={`quick-access-team-${team.id}`}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onClick={() => !isClicked && handleTeamClick(team)}
data-testid={`quick-access-team-${team.name}`}
className={`
onClick={() => !isClicked && handleTeamClick(team)}
data-testid={`quick-access-team-${team.id}`}
className={`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/features/tasks/components/chat/QuickAccessCards.tsx` around
lines 221 - 223, The data-testid on the team card (in QuickAccessCards.tsx) is
currently using the mutable team.name which can change and cause flaky
selectors; update the test id to use a stable, immutable identifier (e.g.,
team.id or team.teamId) instead of team.name in the element where onClick={() =>
!isClicked && handleTeamClick(team)} is defined, and adjust any tests that
assert against the old `quick-access-team-{team.name}` string to use the new
`quick-access-team-{team.id}` format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant