Test ID Implementation Guide for Cross-Platform E2E Tests
Overview
This document explains how to add data-testid attributes to frontend components for cross-platform E2E testing. The test ID constants are defined in frontend-nextjs/src/lib/testIds.ts.
Why Test IDs?
Problem: CSS selectors (classes, IDs) are fragile and break when styling changes.
Solution: Use data-testid attributes that are stable and only used for testing.
Cross-Platform Consistency
- Web (Next.js): Uses
data-testid="..."attributes - Mobile (React Native): Uses
testID="..."props (same values) - Desktop (Tauri): Uses
data-testid="..."attributes (same values)
This ensures E2E tests can use the same selectors across all platforms.
Test ID Constants File
Location: frontend-nextjs/src/lib/testIds.ts
This file exports all test ID constants to avoid typos and ensure consistency.
Usage Example
import { TEST_IDS } from '@/lib/testIds';
// In your component
<input
data-testid={TEST_IDS.AGENT_CHAT.INPUT}
type="text"
placeholder="Type a message..."
/>
<button data-testid={TEST_IDS.AGENT_CHAT.SEND_BUTTON}>
Send
</button>
Required Test IDs by Component
1. Agent Chat Components
File: frontend-nextjs/pages/chat/index.tsx or equivalent
Required test IDs:
agent-chat-input: Message input fieldsend-message-button: Send buttonagent-response: Agent response containerstreaming-indicator: Loading indicator during streaminghistory-button: Toggle history sidebarexecution-history-list: History list containerhistory-item-{index}: Individual history items
2. Canvas Components
File: frontend-nextjs/components/canvas/CanvasContainer.tsx or equivalent
Required test IDs:
canvas-container: Main canvas containercanvas-type-{type}: Canvas type-specific container (generic, docs, email, sheets, orchestration, terminal, coding)close-canvas-button: Close button
3. Authentication Components
File: frontend-nextjs/pages/login.tsx or equivalent
Required test IDs:
login-email-input: Email input fieldlogin-password-input: Password input fieldlogin-submit-button: Login buttonlogin-error-message: Error messagelogout-button: Logout button
4. Form Components
File: Any form component (canvas forms, settings forms, etc.)
Required test IDs:
form-field-{name}: Form field (use field name as suffix)form-submit-button: Submit buttonform-success-message: Success message
5. Skills Components
File: frontend-nextjs/pages/marketplace.tsx or equivalent
Required test IDs:
skills-marketplace-list: Skills listskill-install-button: Install buttonskill-execute-button: Execute buttonskill-output: Output container
6. Settings Components
File: frontend-nextjs/pages/settings/index.tsx or equivalent
Required test IDs:
settings-theme-toggle: Theme togglesettings-notifications-toggle: Notifications togglesettings-preferences: Preferences section
Implementation Checklist
Phase 1: Web Components (Current)
- Add data-testid to agent chat page (
pages/chat/index.tsx) - Add data-testid to canvas components (
components/canvas/) - Add data-testid to login page (
pages/login.tsx) - Add data-testid to skills marketplace (
pages/marketplace.tsx) - Add data-testid to settings page (
pages/settings/index.tsx)
Phase 2: Mobile Components (React Native)
- Create
mobile/src/constants/testIds.tswith same values - Add testID props to mobile AgentChatScreen
- Add testID props to mobile CanvasScreen
- Add testID props to mobile LoginScreen
Phase 3: Desktop Components (Tauri)
- Ensure Tauri components use same data-testid values
- Verify tauri-driver can access data-testid attributes
Example Implementation
Before (Fragile)
// ❌ Bad: Breaks if CSS classes change
<input className="chat-input w-full px-4 py-2" />
<button className="bg-blue-500 text-white">Send</button>
After (Resilient)
// ✅ Good: Stable test selectors
import { TEST_IDS } from '@/lib/testIds';
<input
data-testid={TEST_IDS.AGENT_CHAT.INPUT}
className="chat-input w-full px-4 py-2"
/>
<button
data-testid={TEST_IDS.AGENT_CHAT.SEND_BUTTON}
className="bg-blue-500 text-white"
>
Send
</button>
Testing Your Implementation
After adding test IDs, verify they exist in the DOM:
- Start dev server:
cd frontend-nextjs && npm run dev - Open browser DevTools (F12)
- Go to Elements tab
- Use search (Ctrl+F) for
data-testid - Verify all expected test IDs are present
# Run E2E tests to verify selectors work
cd backend/tests/e2e_ui
pytest tests/cross-platform/test_shared_workflows.py -v
JSDoc Documentation
Add JSDoc comments to components that use test IDs:
/**
* Agent Chat Input Component
*
* **data-testid attributes used by E2E tests - do not remove without updating test plans**
* - agent-chat-input: Main input field
* - send-message-button: Send button
*/
export function AgentChatInput() {
// ...
}
Migration Path
If you encounter existing components without test IDs:
Import test ID constants:
import { TEST_IDS } from '@/lib/testIds';Add data-testid to key interactive elements:
- Inputs, buttons, links
- Containers, lists, grids
- Modals, popovers, dropdowns
Run E2E tests to verify:
pytest backend/tests/e2e_ui/tests/cross-platform/ -vDocument in component JSDoc (see above)
Troubleshooting
E2E tests can't find elements
Problem: Locator.click: Target closed or TimeoutError
Solution:
- Verify data-testid is spelled correctly
- Check browser DevTools to confirm element exists
- Ensure element is visible (not hidden by CSS)
- Check for dynamic IDs (use data-testid instead)
Tests work locally but fail in CI
Problem: Flaky tests in CI environment Solution:
- Ensure data-testid values are constants (not generated)
- Avoid using index-based selectors (e.g.,
li:nth-child(3)) - Use explicit waits:
await page.waitForSelector('[data-testid="..."]')
Mobile testID props not working
Problem: React Native testID not found by Detox Solution:
- Verify
testIDprop (notdata-testid) for React Native - Check mobile/constants/testIds.ts exports match web values
- Ensure component is rendered (not conditionally hidden)
References
- Web Tests:
backend/tests/e2e_ui/tests/cross-platform/test_shared_workflows.py - Test Constants:
frontend-nextjs/src/lib/testIds.ts - Page Objects:
backend/tests/e2e_ui/pages/cross_platform_objects.py - Playwright Selectors: https://playwright.dev/docs/selectors
- Detox Selectors: https://wix.github.io/Detox/docs/api/simulation/matchers
Summary
By following this guide, you ensure that:
- E2E tests are resilient to styling changes
- Test selectors are consistent across web, mobile, and desktop
- Tests are easier to maintain and debug
- New developers can understand the testing approach
Remember: Test IDs are for testing only. Don't use them for CSS styling or JavaScript logic.