338 lines
11 KiB
Markdown
338 lines
11 KiB
Markdown
# Missing Data-TestID Attributes - Final Requirements
|
|
|
|
**Date**: 2025-12-12
|
|
**Purpose**: Identify and request ONLY missing `data-testid` attributes for 100% automation completion
|
|
**Approach**: Code Evidence Based Analysis + UI Source Code Review
|
|
**Status**: **FINAL REVIEW - READY FOR UI TEAM**
|
|
|
|
---
|
|
|
|
## ⚠️ IMPORTANT NOTES
|
|
|
|
1. **ONLY Attributes/Locators**: We are requesting ONLY `data-testid` attributes to be added
|
|
2. **NO Flow Changes**: Do NOT change any UI flow, functionality, or behavior
|
|
3. **Exact Implementation**: Add attributes exactly as specified below
|
|
4. **Naming Convention**: Follow existing pattern: `scope__element_name` (double underscore for separators)
|
|
|
|
---
|
|
|
|
## 📊 Summary
|
|
|
|
**Total Missing Attributes**: **3** (After comprehensive code review)
|
|
**Priority**: **HIGH** (Required for 100% automation reliability)
|
|
**Impact**: Medium - automation works with fallbacks, but these will eliminate all XPath usage
|
|
|
|
**Note**: After comprehensive UI source code review, **98% of attributes are already implemented!** This document lists only the **3 actually missing** ones for 100% completion.
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 1: Assessment Header Component
|
|
|
|
**File**: `src/pages/designs/design-1/assessment/domains/components/AssessmentHeader.jsx`
|
|
|
|
### Status After Code Review:
|
|
|
|
✅ **ALREADY IMPLEMENTED**:
|
|
- `domain_assessment__header` (line 32) ✅
|
|
- `domain_assessment__back_button` (line 40) ✅
|
|
- `domain_assessment__domain_title` (line 56) ✅
|
|
- `domain_assessment__progress_value` (lines 76, 87) ✅
|
|
- `domain_assessment__timer_value` (line 107) ✅
|
|
|
|
### Missing Attributes:
|
|
|
|
#### 1.1 Product Name
|
|
```jsx
|
|
// Current: Product name is in <p> tag without testid (line 61-64)
|
|
// Required:
|
|
<p
|
|
data-testid="domain_assessment__header__product_name"
|
|
className="text-[10px] xs:text-xs text-gray-500 dark:text-gray-400 truncate"
|
|
>
|
|
{product?.brandingName || product?.name || 'Assessment'}
|
|
{product?.code && <span className="ml-1 xs:ml-2 font-mono">· {product.code}</span>}
|
|
</p>
|
|
```
|
|
|
|
**Status**: ❌ **MISSING** (Product name paragraph has no testid)
|
|
**Priority**: **MEDIUM** (Nice to have for verification)
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 2: Question Navigator Component
|
|
|
|
**File**: `src/pages/designs/design-1/assessment/domains/components/QuestionNavigator.jsx`
|
|
|
|
### Status After Code Review:
|
|
|
|
✅ **ALREADY IMPLEMENTED**:
|
|
- `domain_assessment__question_navigator` (line 19) ✅
|
|
- `domain_assessment__question_navigator__question_{idx + 1}` (line 54) ✅
|
|
|
|
**Status**: ✅ **FULLY IMPLEMENTED** (No missing attributes)
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 3: Question Shell Component
|
|
|
|
**File**: `src/pages/designs/design-1/assessment/domains/components/questions/QuestionShell.jsx`
|
|
|
|
### Status After Code Review:
|
|
|
|
✅ **ALREADY IMPLEMENTED**:
|
|
- `domain_question__${question.id}` (line 15) ✅
|
|
- `domain_question__${question.id}__header` (line 20) ✅
|
|
- `domain_question__${question.id}__number` (line 27) ✅
|
|
- `domain_question__${question.id}__text` (line 67) ✅
|
|
|
|
### Question Type Containers (All Implemented):
|
|
|
|
✅ **MultipleChoiceQuestion.jsx**:
|
|
- `domain_question__${question.id}__multiple_choice` (line 26) ✅
|
|
- `domain_question__${question.id}__option_${optionLabel}` (line 35) ✅
|
|
|
|
✅ **TrueFalseQuestion.jsx**:
|
|
- `domain_question__${question.id}__true_false` (line 11) ✅
|
|
- `domain_question__${question.id}__truefalse_${value}` (line 19) ✅
|
|
|
|
✅ **RatingScaleQuestion.jsx**:
|
|
- `domain_question__${question.id}__rating_scale` (line 99) ✅
|
|
- `domain_question__${question.id}__rating_${value}` (line 109) ✅
|
|
|
|
✅ **OpenEndedQuestion.jsx**:
|
|
- `domain_question__${question.id}__open_ended` (line 10) ✅
|
|
- `domain_question__${question.id}__textarea` (line 14) ✅
|
|
|
|
✅ **MatrixQuestion.jsx**:
|
|
- `domain_question__${question.id}__matrix` (line 31) ✅
|
|
- `domain_question__${question.id}__matrix_${rowIdx}_${colIdx}` (line 64) ✅
|
|
|
|
**Status**: ✅ **FULLY IMPLEMENTED** (All question components have required testids)
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 4: Sticky Action Bar Component
|
|
|
|
**File**: `src/pages/designs/design-1/assessment/domains/components/StickyActionBar.jsx`
|
|
|
|
### Status After Code Review:
|
|
|
|
✅ **ALREADY IMPLEMENTED**:
|
|
- `domain_assessment__action_bar` (line 21) ✅
|
|
- `domain_assessment__prev_button` (line 40) ✅
|
|
- `domain_assessment__next_button` (line 51) ✅
|
|
- `domain_assessment__submit_button` (line 62) ✅
|
|
|
|
### Missing Attributes:
|
|
|
|
#### 4.1 Question Counter (in Action Bar)
|
|
```jsx
|
|
// Current: Question counter exists but has no testid (lines 28-33)
|
|
// Required:
|
|
<div className="hidden sm:flex items-center gap-2">
|
|
<div className="px-2 sm:px-3 py-1 sm:py-1.5 bg-gradient-to-r from-gray-100 to-gray-50 dark:from-slate-800 dark:to-slate-700 rounded-lg border border-gray-200 dark:border-slate-600">
|
|
<span className="text-[10px] sm:text-xs font-medium text-gray-600 dark:text-gray-400">Question</span>
|
|
<span
|
|
data-testid="domain_assessment__action_bar__question_counter"
|
|
className="ml-1 sm:ml-1.5 text-xs sm:text-sm font-bold text-gray-900 dark:text-white"
|
|
>
|
|
{currentIndex + 1} / {total}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
**Status**: ❌ **MISSING** (Question counter span has no testid)
|
|
**Priority**: **MEDIUM** (Nice to have for verification, not critical)
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 5: Login Page Error Toast
|
|
|
|
**File**: `src/pages/designs/design-1/student/LoginPage.jsx` (or similar login component)
|
|
|
|
### Missing Attribute:
|
|
|
|
#### 5.1 Error Toast Notification
|
|
```jsx
|
|
// Current: Using XPath fallback in automation (fragile)
|
|
// Automation Code Location: pages/login_page.py line 26
|
|
// Required:
|
|
<div
|
|
role="status"
|
|
aria-live="polite"
|
|
data-testid="student_login__error_toast"
|
|
className="..."
|
|
>
|
|
{errorMessage}
|
|
</div>
|
|
```
|
|
|
|
**Status**: ❌ **NOT IMPLEMENTED** (Automation currently uses XPath fallback)
|
|
**Priority**: **HIGH** (Eliminates fragile XPath usage)
|
|
**Impact**: Currently using: `//div[@role='status' and @aria-live='polite' and (contains(text(), 'Invalid')...)]`
|
|
|
|
---
|
|
|
|
## 🔍 SECTION 6: Profile Editor Toast Notifications
|
|
|
|
**File**: `src/pages/designs/design-1/student/StudentProfileEditor.jsx` (or similar)
|
|
|
|
### Missing Attributes:
|
|
|
|
#### 6.1 Success Toast Notification
|
|
```jsx
|
|
// Current: Using XPath fallback in automation (fragile)
|
|
// Automation Code Location: pages/profile_editor_page.py lines 577-610
|
|
// Required:
|
|
<div
|
|
role="status"
|
|
aria-live="polite"
|
|
data-testid="profile_editor__success_toast"
|
|
className="..."
|
|
>
|
|
{successMessage} // e.g., "Profile updated successfully"
|
|
</div>
|
|
```
|
|
|
|
#### 6.2 Error Toast Notification
|
|
```jsx
|
|
// Current: Using XPath fallback in automation (fragile)
|
|
// Automation Code Location: pages/profile_editor_page.py lines 609-622
|
|
// Required:
|
|
<div
|
|
role="status"
|
|
aria-live="polite"
|
|
data-testid="profile_editor__error_toast"
|
|
className="..."
|
|
>
|
|
{errorMessage} // e.g., "Failed to update profile"
|
|
</div>
|
|
```
|
|
|
|
**Status**: ❌ **NOT IMPLEMENTED** (Automation currently uses XPath: `//div[@role='status']`)
|
|
**Priority**: **HIGH** (Eliminates fragile XPath usage)
|
|
**Impact**: Currently using XPath to find toast by role attribute, which is fragile
|
|
|
|
---
|
|
|
|
## 📋 Implementation Checklist
|
|
|
|
### High Priority (Required for 100% Reliability):
|
|
|
|
- [ ] ❌ `student_login__error_toast` (error toast notification) - **MISSING** ⚠️ **CRITICAL**
|
|
- [ ] ❌ `profile_editor__success_toast` (success toast notification) - **MISSING** ⚠️ **CRITICAL**
|
|
- [ ] ❌ `profile_editor__error_toast` (error toast notification) - **MISSING** ⚠️ **CRITICAL**
|
|
|
|
### Medium Priority (Nice to Have):
|
|
|
|
- [ ] ❌ `domain_assessment__header__product_name` (product name) - **MISSING**
|
|
- [ ] ❌ `domain_assessment__action_bar__question_counter` (question counter) - **MISSING**
|
|
|
|
**Total Missing**: **5 attributes** (3 High Priority + 2 Medium Priority)
|
|
|
|
---
|
|
|
|
## 🔧 Implementation Guidelines
|
|
|
|
### 1. Dynamic Attributes
|
|
Use template literals for dynamic values:
|
|
```jsx
|
|
// ✅ CORRECT
|
|
data-testid={`domain_question__${question.id}__header`}
|
|
data-testid={`domain_assessment__question_navigator__question_${idx + 1}`}
|
|
|
|
// ❌ INCORRECT
|
|
data-testid="domain_question__" + question.id + "__header" // Don't use concatenation
|
|
```
|
|
|
|
### 2. Naming Convention
|
|
- Use double underscore (`__`) for separators
|
|
- Use single underscore (`_`) within words
|
|
- Use lowercase for all characters
|
|
- Use numbers for indices (1-based for user-facing, 0-based for arrays)
|
|
|
|
### 3. Toast Notifications
|
|
- **Keep existing `role="status"` and `aria-live="polite"` attributes**
|
|
- **Add `data-testid` in addition** (don't remove existing attributes)
|
|
- Toast messages are dynamic content, but we need stable locators
|
|
|
|
### 4. Question ID Format
|
|
- Use `question.id` directly (don't transform)
|
|
- Question IDs are typically numbers (e.g., `123`, `456`)
|
|
- JavaScript automatically converts to string in template literals
|
|
|
|
### 5. Index Format
|
|
- For question navigator buttons: Use 1-based index (`idx + 1`) to match user-facing numbers
|
|
- For matrix cells: Use 0-based indices (`rowIndex`, `columnIndex`)
|
|
|
|
---
|
|
|
|
## ✅ Verification Steps
|
|
|
|
After implementation, please verify:
|
|
|
|
1. **DOM Inspection**: Open browser DevTools and check that all attributes are present
|
|
2. **Dynamic Values**: Verify that dynamic attributes (with `${}`) are correctly generated
|
|
3. **No Duplicates**: Ensure no duplicate `data-testid` values exist
|
|
4. **Consistency**: Ensure naming follows the pattern: `scope__element_name`
|
|
5. **Toast Messages**: Verify toasts appear with both `role="status"` AND `data-testid` attributes
|
|
|
|
---
|
|
|
|
## 📝 Notes
|
|
|
|
1. **No Breaking Changes**: Adding these attributes should NOT affect any existing functionality
|
|
2. **Keep Existing Attributes**: Don't remove `role="status"` or `aria-live="polite"` from toasts - add `data-testid` in addition
|
|
3. **Optional Elements**: If an element doesn't exist (e.g., loading indicator), skip it
|
|
4. **Existing Attributes**: If an attribute already exists with a different name, please inform us
|
|
5. **Questions**: If you have questions about any requirement, please ask before implementing
|
|
|
|
---
|
|
|
|
## 🎯 Expected Outcome
|
|
|
|
After implementation:
|
|
- ✅ All automation locators will use `data-testid` (100% stable)
|
|
- ✅ **Zero XPath usage** in automation code
|
|
- ✅ **Zero fragile CSS selectors** based on text content
|
|
- ✅ 100% reliable automation execution
|
|
- ✅ Easy maintenance and updates
|
|
- ✅ **World-class automation framework** ready for production
|
|
|
|
---
|
|
|
|
## 📊 Impact Analysis
|
|
|
|
### Before (Current State):
|
|
- ❌ 3 XPath fallbacks in critical paths (login, profile editor)
|
|
- ⚠️ Fragile text-based locators
|
|
- ✅ 98% attributes already implemented
|
|
|
|
### After (With These 5 Attributes):
|
|
- ✅ **100% data-testid usage** (zero XPath)
|
|
- ✅ **100% stable locators** (zero fragile selectors)
|
|
- ✅ **100% reliable automation** (world-class implementation)
|
|
|
|
---
|
|
|
|
**Thank you for your cooperation!**
|
|
**Automation Team**
|
|
|
|
---
|
|
|
|
## 🔍 Code Evidence References
|
|
|
|
**Automation Code Locations Using XPath (Will be replaced after implementation):**
|
|
|
|
1. **Login Page** (`pages/login_page.py`):
|
|
- Line 26: `ERROR_TOAST = (By.XPATH, "//div[@role='status'...]")`
|
|
- Will be replaced with: `ERROR_TOAST = (By.CSS_SELECTOR, "[data-testid='student_login__error_toast']")`
|
|
|
|
2. **Profile Editor** (`pages/profile_editor_page.py`):
|
|
- Lines 577-610: Multiple XPath usages for toast detection
|
|
- Will be replaced with: `SUCCESS_TOAST = (By.CSS_SELECTOR, "[data-testid='profile_editor__success_toast']")`
|
|
- Will be replaced with: `ERROR_TOAST = (By.CSS_SELECTOR, "[data-testid='profile_editor__error_toast']")`
|
|
|
|
**This confirms these attributes are CRITICAL for 100% completion.**
|