# UI Automation IDs ## Overview The UI reflection system provides a live, high-level JSON description of the application's UI state. To ensure proper integration with automated testing and LLM-driven interactions, all UI components must maintain consistency between their UI state IDs and DOM data-automation-id attributes. ## Parent-Child Relationships Components automatically inherit their parent's ID through React context, eliminating the need to manually wire parentId everywhere: ```typescript // Parent container sets the context {/* Children automatically know their parent */} {/* gets ticketing-dashboard as parent */} {/* gets ticketing-dashboard as parent */} ``` ## Naming Conventions Follow these patterns for component IDs: 1. **Screen/Page Components**: ```typescript // Base page ID id="ticketing-dashboard" ``` 2. **Subcontainers**: ```typescript // Major sections use parent ID + purpose id={`${parentId}-filters`} // ticketing-dashboard-filters id={`${parentId}-table`} // ticketing-dashboard-table ``` 3. **UI Components**: ```typescript // Individual elements use parent ID + type id={`${parentId}-status-select`} // ticketing-dashboard-filters-status-select id={`${parentId}-search-input`} // ticketing-dashboard-filters-search-input ``` ## Sidebar Menu ID Convention The sidebar menu items use a double-prefix pattern in their DOM automation IDs. The `Sidebar` component generates an `id` of `menu-{name}` for each item, which is then passed to `SidebarMenuItem`. The `SidebarMenuItem` renders the element with a `data-automation-id` of `sidebar-menu-menu-{name}`, resulting in the `menu-` prefix appearing twice. For example, the Home menu item renders as: ``` data-automation-id="sidebar-menu-menu-home" ``` Other examples: - Tickets: `sidebar-menu-menu-tickets` - Companies: `sidebar-menu-menu-companies` - Settings: `sidebar-menu-menu-settings` When writing tests or automation scripts targeting sidebar items, use the full double-prefix form (`sidebar-menu-menu-{name}`). ## The useAutomationIdAndRegister Hook Use this hook to combine UI reflection registration and data-automation-id props: ```typescript function MyComponent({ id, ...props }) { // Register with reflection system and get DOM props const { automationIdProps, updateMetadata } = useAutomationIdAndRegister({ id, // Optional - will auto-generate if not provided type: 'container', label: 'My Component' }); return
; } ``` ### Features 1. **Automatic ID Generation**: ```typescript // With explicit ID const { automationIdProps } = useAutomationIdAndRegister({ id: `${parentId}-filters`, type: 'container' }); // With auto-generated ID const { automationIdProps } = useAutomationIdAndRegister({ type: 'container' // generates like: container-1, container-2, etc. }); ``` 2. **Parent Context Integration**: ```typescript // Auto-generated IDs include parent context parentId: 'my-screen' auto-generated: 'my-screen-button-1' ``` 3. **Single Source of Truth**: - One hook call provides both reflection registration and DOM attributes - No chance of mismatch between UI state and DOM - Type-safe through TypeScript generics ## Core Components Over 52 UI components now implement the `useAutomationIdAndRegister` pattern, including but not limited to: - Button (`packages/ui/src/components/Button.tsx`) - Input (`packages/ui/src/components/Input.tsx`) - Dialog (`packages/ui/src/components/Dialog.tsx`) - SearchableSelect, CustomSelect, AsyncSearchableSelect - TextArea, SearchInput, TagInput - ClientPicker, UserPicker, ContactPicker, CountryPicker - DateTimePicker, DatePicker, TimePicker - GenericDialog, CategoryPicker, BoardPicker When creating new components that use the UI reflection system, follow these examples to maintain consistency. ## Testing When writing tests, always use the component's ID to locate elements: ```typescript // Good - uses data-automation-id that matches UI state cy.get('[data-automation-id="ticketing-dashboard-filters-status-select"]').click(); // Bad - uses other selectors that might change cy.get('.status-select').click(); cy.get('select:contains("Status")').click(); ``` ## Benefits 1. **Automated Testing**: - Consistent, predictable IDs make tests reliable - Parent-child relationships reflected in ID structure - Auto-generated IDs maintain uniqueness 2. **LLM Integration**: - Hierarchical component structure is clear from IDs - Consistent naming makes UI state easy to understand - Automatic parent-child tracking improves accuracy 3. **Developer Experience**: - No manual parentId prop passing - Auto-generated IDs reduce boilerplate - Single hook call for all UI reflection needs - Type-safe through TypeScript 4. **Maintenance**: - Consistent naming conventions - Clear component hierarchy - Reduced coupling between tests and implementation - Single source of truth for IDs ## Implementation Details The UI reflection system uses React's Context API to maintain a live representation of the UI state. Each component that registers with the system contributes to this state, and the data-automation-id attributes provide a direct mapping between the logical UI state and the actual DOM elements. The system now includes: - ReflectionParentContext for automatic parent-child relationships - useAutomationIdAndRegister hook for unified registration and DOM props - Automatic ID generation with consistent naming patterns - Type-safe component registration through TypeScript See also: - [UI Reflection System](ui_reflection_system.md) - [Development Guide](../getting-started/development_guide.md)