849 lines
27 KiB
Markdown
849 lines
27 KiB
Markdown
# 🎯 COMPLETE DATA-TESTID REQUIREMENTS
|
|
## For UI Development Team - All Components
|
|
|
|
**Date:** 2025-01-20
|
|
**Priority:** 🔴 **CRITICAL - BLOCKING AUTOMATION**
|
|
**Status:** ❌ **ALL ATTRIBUTES MISSING**
|
|
**Version:** 1.0 - Standalone Complete Document
|
|
|
|
---
|
|
|
|
## 📋 **EXECUTIVE SUMMARY**
|
|
|
|
This document contains **ALL** required `data-testid` attributes for automation testing across **ALL** components.
|
|
|
|
**Total Required Attributes:** ~214+ attributes across 2 components
|
|
|
|
### **Components Requiring Updates:**
|
|
1. **Student Profile Editor** (`StudentProfileEditor.jsx`) - ~200+ attributes
|
|
2. **Mandatory Password Reset Modal** (`MandatoryPasswordResetModal.jsx`) - 14 attributes
|
|
|
|
---
|
|
|
|
## 🔑 **NAMING CONVENTION (MANDATORY - READ THIS FIRST)**
|
|
|
|
### **Pattern:**
|
|
```
|
|
{scope}__{element_name}_{type}
|
|
```
|
|
|
|
### **Rules:**
|
|
1. **Scope:** Component-specific scope (e.g., `profile_editor`, `mandatory_reset`)
|
|
2. **Separator:** **Double underscore** `__` between scope and element name
|
|
3. **Element Name:** **Snake_case** (lowercase with underscores)
|
|
4. **Type Suffix:**
|
|
- `_input` for text inputs
|
|
- `_select` for dropdowns
|
|
- `_textarea` for text areas
|
|
- `_checkbox` for checkboxes
|
|
- `_button` for buttons
|
|
- `_tab` for tab buttons
|
|
|
|
### **Examples:**
|
|
- ✅ `profile_editor__first_name_input`
|
|
- ✅ `mandatory_reset__continue_button`
|
|
- ✅ `profile_editor__tab_personal_information`
|
|
- ❌ `profile_editor_first_name` (single underscore - WRONG)
|
|
- ❌ `profileEditor__first_name` (camelCase - WRONG)
|
|
|
|
### **Dynamic Elements:**
|
|
For dynamic elements (like checkboxes in lists), use:
|
|
```
|
|
{scope}__{base_name}__{formatted_option}
|
|
```
|
|
|
|
**Example:**
|
|
- `profile_editor__short_term_focus__01_academics`
|
|
- `profile_editor__strength__1_quick_learning`
|
|
|
|
---
|
|
|
|
## 📚 **PART 1: STUDENT PROFILE EDITOR**
|
|
|
|
**File:** `src/pages/StudentProfileEditor.jsx`
|
|
**Scope:** `profile_editor`
|
|
**Total Attributes:** ~200+
|
|
|
|
---
|
|
|
|
### **1.1 PAGE-LEVEL ELEMENTS**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Page container | `profile_editor__page` | Line 1516 | 🔴 CRITICAL |
|
|
| Progress value display | `profile_editor__progress_value` | Line 1577 | 🔴 CRITICAL |
|
|
| Missing fields toggle button | `profile_editor__missing_fields_toggle` | Line 1580-1586 | 🟡 IMPORTANT |
|
|
| Back button (header) | `profile_editor__back_button` | Line 1555-1560 | 🟡 IMPORTANT |
|
|
|
|
**Implementation:**
|
|
```jsx
|
|
<div data-testid="profile_editor__page">
|
|
<span data-testid="profile_editor__progress_value">{progress}%</span>
|
|
<button data-testid="profile_editor__missing_fields_toggle">...</button>
|
|
<button data-testid="profile_editor__back_button">Back</button>
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
### **1.2 TAB NAVIGATION**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Tab container | `profile_editor__tabs_container` | Line 1693-1700 | 🔴 CRITICAL |
|
|
| Tab scroll left button | `profile_editor__tabs_scroll_left_button` | Line 1683-1690 | 🟡 IMPORTANT |
|
|
| Tab scroll right button | `profile_editor__tabs_scroll_right_button` | Line 1729-1736 | 🟡 IMPORTANT |
|
|
|
|
#### **Tab Buttons (9 tabs) - 🔴 CRITICAL**
|
|
|
|
**Format:** `profile_editor__tab_{formatTestId(section.title)}`
|
|
|
|
| Tab Index | Tab Title | Required Attribute | Priority |
|
|
|-----------|-----------|-------------------|----------|
|
|
| 0 | Personal Information | `profile_editor__tab_personal_information` | 🔴 CRITICAL |
|
|
| 1 | Contact Information | `profile_editor__tab_contact_information` | 🔴 CRITICAL |
|
|
| 2 | Parent/Guardian | `profile_editor__tab_parent_guardian` | 🔴 CRITICAL |
|
|
| 3 | Education Details | `profile_editor__tab_education_details` | 🔴 CRITICAL |
|
|
| 4 | Focus Areas | `profile_editor__tab_focus_areas` | 🔴 CRITICAL |
|
|
| 5 | Self-Assessment | `profile_editor__tab_self_assessment` | 🔴 CRITICAL |
|
|
| 6 | Hobbies & Clubs | `profile_editor__tab_hobbies_clubs` | 🔴 CRITICAL |
|
|
| 7 | Achievements | `profile_editor__tab_achievements` | 🔴 CRITICAL |
|
|
| 8 | Expectations | `profile_editor__tab_expectations` | 🔴 CRITICAL |
|
|
|
|
**Implementation (Line 1703):**
|
|
```jsx
|
|
<button
|
|
key={idx}
|
|
onClick={() => setActiveTab(idx)}
|
|
data-testid={`profile_editor__tab_${formatTestId(section.title)}`}
|
|
className={...}
|
|
>
|
|
```
|
|
|
|
**formatTestId Function (Add at top of file, Line ~23):**
|
|
```javascript
|
|
const formatTestId = (value = '') => {
|
|
return value
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '_') // Replace all non-alphanumeric with underscore
|
|
.replace(/^_|_$/g, '') // Remove leading/trailing underscores
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### **1.3 SECTION 1: PERSONAL INFORMATION** (Tab 0)
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| First Name input | `profile_editor__first_name_input` | Line 767-773 | 🔴 CRITICAL |
|
|
| Last Name input | `profile_editor__last_name_input` | Line 776-782 | 🔴 CRITICAL |
|
|
| Gender select | `profile_editor__gender_select` | Line 785-794 | 🔴 CRITICAL |
|
|
| Date of Birth input | `profile_editor__dob_input` | Line 797-802 | 🔴 CRITICAL |
|
|
| Nationality input | `profile_editor__nationality_input` | Line 805-811 | 🔴 CRITICAL |
|
|
| Language input | `profile_editor__language_input` | Line 814-820 | 🟡 IMPORTANT |
|
|
| Student ID Number input | `profile_editor__student_id_input` | Line 823-829 | 🟡 IMPORTANT |
|
|
| Student CPID input | `profile_editor__student_cpid_input` | Line 832-838 | 🟡 IMPORTANT |
|
|
| Specially Abled checkbox | `profile_editor__specially_abled_checkbox` | Line 843-848 | 🟡 IMPORTANT |
|
|
| Specially Abled Details textarea | `profile_editor__specially_abled_details_textarea` | Line 854-860 | 🟢 OPTIONAL |
|
|
|
|
**Implementation Example:**
|
|
```jsx
|
|
<input
|
|
type="text"
|
|
value={form.firstName}
|
|
onChange={(e) => handleFieldChange('firstName', e.target.value)}
|
|
data-testid="profile_editor__first_name_input"
|
|
className={...}
|
|
/>
|
|
```
|
|
|
|
---
|
|
|
|
### **1.4 SECTION 2: CONTACT INFORMATION** (Tab 1)
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Email input | `profile_editor__email_input` | Line 873-879 | 🔴 CRITICAL |
|
|
| Phone input | `profile_editor__phone_input` | Line 882-889 | 🔴 CRITICAL |
|
|
| Address input | `profile_editor__address_input` | Line 892-898 | 🔴 CRITICAL |
|
|
| City input | `profile_editor__city_input` | Line 901-907 | 🔴 CRITICAL |
|
|
| State input | `profile_editor__state_input` | Line 910-916 | 🔴 CRITICAL |
|
|
| ZIP Code input | `profile_editor__zip_code_input` | Line 919-925 | 🔴 CRITICAL |
|
|
| Native State input | `profile_editor__native_state_input` | Line 928-934 | 🟡 IMPORTANT |
|
|
|
|
---
|
|
|
|
### **1.5 SECTION 3: PARENT/GUARDIAN** (Tab 2)
|
|
|
|
#### **Father's Details:**
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Father Full Name input | `profile_editor__father_full_name_input` | Line 953-959 | 🔴 CRITICAL |
|
|
| Father Age Range select | `profile_editor__father_age_range_select` | Line 962-972 | 🔴 CRITICAL |
|
|
| Father Occupation input | `profile_editor__father_occupation_input` | Line 975-981 | 🔴 CRITICAL |
|
|
| Father Email input | `profile_editor__father_email_input` | Line 984-990 | 🔴 CRITICAL |
|
|
|
|
#### **Mother's Details:**
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Mother Full Name input | `profile_editor__mother_full_name_input` | Line 1002-1008 | 🔴 CRITICAL |
|
|
| Mother Age Range select | `profile_editor__mother_age_range_select` | Line 1011-1021 | 🔴 CRITICAL |
|
|
| Mother Occupation input | `profile_editor__mother_occupation_input` | Line 1024-1030 | 🔴 CRITICAL |
|
|
| Mother Email input | `profile_editor__mother_email_input` | Line 1033-1039 | 🔴 CRITICAL |
|
|
|
|
#### **Guardian (If Different):**
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Guardian Different checkbox | `profile_editor__guardian_different_checkbox` | Line 1047-1052 | 🟡 IMPORTANT |
|
|
| Guardian Full Name input | `profile_editor__guardian_full_name_input` | Line 1061-1067 | 🟡 IMPORTANT |
|
|
| Guardian Relationship input | `profile_editor__guardian_relationship_input` | Line 1070-1076 | 🟡 IMPORTANT |
|
|
| Guardian Phone input | `profile_editor__guardian_phone_input` | Line 1079-1086 | 🟡 IMPORTANT |
|
|
| Guardian Email input | `profile_editor__guardian_email_input` | Line 1089-1095 | 🟡 IMPORTANT |
|
|
| Guardian Address input | `profile_editor__guardian_address_input` | Line 1099-1105 | 🟡 IMPORTANT |
|
|
|
|
---
|
|
|
|
### **1.6 SECTION 4: EDUCATION DETAILS** (Tab 3)
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Full Name input | `profile_editor__full_name_input` | Line 1128-1134 | 🔴 CRITICAL |
|
|
| Current Grade/Class input | `profile_editor__current_grade_input` | Line 1137-1143 | 🔴 CRITICAL |
|
|
| Section/Subject input | `profile_editor__section_input` | Line 1146-1152 | 🔴 CRITICAL |
|
|
| Board/Stream select | `profile_editor__board_stream_select` | Line 1155-1167 | 🔴 CRITICAL |
|
|
|
|
---
|
|
|
|
### **1.7 SECTION 5: FOCUS AREAS** (Tab 4)
|
|
|
|
#### **Short-term Focus Areas:**
|
|
**Format:** `profile_editor__short_term_focus__{formatTestId(option)}`
|
|
|
|
**Required for each option in FOCUS_AREAS_ADOLESCENT/FOCUS_AREAS_ADULT:**
|
|
- `profile_editor__short_term_focus__01_academics`
|
|
- `profile_editor__short_term_focus__02_family`
|
|
- `profile_editor__short_term_focus__03_health`
|
|
- ... (all options)
|
|
- `profile_editor__short_term_focus__10_others` (or `20_others` for adult)
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__short_term_focus_others_text` (Line 1198-1204)
|
|
|
|
#### **Long-term Focus Areas:**
|
|
**Format:** `profile_editor__long_term_focus__{formatTestId(option)}`
|
|
|
|
**Required for each option:**
|
|
- `profile_editor__long_term_focus__01_academics`
|
|
- ... (all options)
|
|
- `profile_editor__long_term_focus__10_others` (or `20_others`)
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__long_term_focus_others_text` (Line 1228-1234)
|
|
|
|
**Implementation - Update MultiSelectPicker Component (Line 174-186):**
|
|
```jsx
|
|
const MultiSelectPicker = ({ options, selectedItems, onToggle, maxItems, icon: Icon, testIdPrefix }) => {
|
|
// ... existing code ...
|
|
|
|
return (
|
|
<div className="space-y-2 xs:space-y-3">
|
|
{options.map((option) => {
|
|
// ... existing code ...
|
|
return (
|
|
<label key={option} className={...}>
|
|
<input
|
|
type="checkbox"
|
|
checked={isSelected}
|
|
disabled={isDisabled}
|
|
onChange={...}
|
|
data-testid={testIdPrefix ? `${testIdPrefix}__${formatTestId(option)}` : undefined}
|
|
className={...}
|
|
/>
|
|
{/* ... */}
|
|
</label>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Usage:**
|
|
```jsx
|
|
<MultiSelectPicker
|
|
options={focusAreas}
|
|
selectedItems={form.shortTermFocusAreas}
|
|
onToggle={...}
|
|
maxItems={3}
|
|
testIdPrefix="profile_editor__short_term_focus" // ADD THIS
|
|
/>
|
|
```
|
|
|
|
---
|
|
|
|
### **1.8 SECTION 6: SELF-ASSESSMENT** (Tab 5)
|
|
|
|
#### **Strengths:**
|
|
**Format:** `profile_editor__strength__{formatTestId(option)}`
|
|
|
|
**Required for each option in STRENGTHS_OPTIONS (19 options):**
|
|
- `profile_editor__strength__1_quick_learning`
|
|
- `profile_editor__strength__2_curiosity`
|
|
- `profile_editor__strength__3_problem_solving`
|
|
- ... (all 19 options)
|
|
- `profile_editor__strength__19_others`
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__strength_others_text` (Line 1268-1274)
|
|
|
|
#### **Areas of Improvement:**
|
|
**Format:** `profile_editor__improvement__{formatTestId(option)}`
|
|
|
|
**Required for each option (same as strengths, 19 options):**
|
|
- `profile_editor__improvement__1_quick_learning`
|
|
- ... (all 19 options)
|
|
- `profile_editor__improvement__19_others`
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__improvement_others_text` (Line 1298-1304)
|
|
|
|
**Usage:**
|
|
```jsx
|
|
<MultiSelectPicker
|
|
options={STRENGTHS_OPTIONS}
|
|
selectedItems={form.strengths}
|
|
onToggle={...}
|
|
maxItems={3}
|
|
testIdPrefix="profile_editor__strength" // ADD THIS
|
|
/>
|
|
```
|
|
|
|
---
|
|
|
|
### **1.9 SECTION 7: HOBBIES & CLUBS** (Tab 6)
|
|
|
|
#### **Hobbies/Interests:**
|
|
**Format:** `profile_editor__hobby__{formatTestId(option)}`
|
|
|
|
**Required for each option in HOBBIES_OPTIONS (12 options):**
|
|
- `profile_editor__hobby__01_reading`
|
|
- `profile_editor__hobby__02_playing_musical_instruments`
|
|
- ... (all 12 options)
|
|
- `profile_editor__hobby__12_other`
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__hobby_other_text` (Line 1337-1343)
|
|
|
|
#### **Clubs or Teams:**
|
|
**Format:** `profile_editor__club_{formatTestId(club)}`
|
|
|
|
**Required for each option in CLUBS_OPTIONS (13 options):**
|
|
- `profile_editor__club_0_no_clubs_teams`
|
|
- `profile_editor__club_1_science_club`
|
|
- `profile_editor__club_2_mathematics_club`
|
|
- ... (all 13 options)
|
|
- `profile_editor__club_12_other`
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__club_other_text` (Line 1410-1416)
|
|
|
|
**Implementation for Clubs (Line 1372):**
|
|
```jsx
|
|
<input
|
|
type="checkbox"
|
|
checked={isChecked}
|
|
disabled={isDisabled}
|
|
onChange={...}
|
|
data-testid={`profile_editor__club_${formatTestId(club)}`}
|
|
className={...}
|
|
/>
|
|
```
|
|
|
|
---
|
|
|
|
### **1.10 SECTION 8: ACHIEVEMENTS** (Tab 7)
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Academics textarea | `profile_editor__achievement_academics_textarea` | Line 1432-1438 | 🔴 CRITICAL |
|
|
| Sports textarea | `profile_editor__achievement_sports_textarea` | Line 1441-1447 | 🔴 CRITICAL |
|
|
| Cultural/Arts textarea | `profile_editor__achievement_cultural_textarea` | Line 1450-1456 | 🔴 CRITICAL |
|
|
| Trained/Certified textarea | `profile_editor__achievement_trained_textarea` | Line 1460-1466 | 🟡 IMPORTANT |
|
|
| Others textarea | `profile_editor__achievement_others_textarea` | Line 1470-1476 | 🔴 CRITICAL |
|
|
|
|
**Note:** Trained/Certified field is conditional (only for ageCategory === '18-23').
|
|
|
|
---
|
|
|
|
### **1.11 SECTION 9: EXPECTATIONS** (Tab 8)
|
|
|
|
**Format:** `profile_editor__expectation__{formatTestId(option)}`
|
|
|
|
**Required for each option in EXPECTATIONS_OPTIONS (10 options):**
|
|
- `profile_editor__expectation__1_self_understanding_gain_deeper_insights_into_their_personality_strengths_and_areas_for_growth`
|
|
- `profile_editor__expectation__2_career_guidance_clear_recommendations_on_suitable_career_paths_or_college_majors_based_on_their_interests_and_abilities_backed_by_scientific_tool`
|
|
- ... (all 10 options)
|
|
- `profile_editor__expectation__10_others`
|
|
|
|
**Others Text Input:**
|
|
- `profile_editor__expectation_others_text` (Line 1500-1506)
|
|
|
|
**Note:** Expectations have very long text. The `formatTestId` function will handle this automatically.
|
|
|
|
---
|
|
|
|
### **1.12 NAVIGATION BUTTONS**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Previous button | `profile_editor__prev_button` | Line 1770-1778 | 🔴 CRITICAL |
|
|
| Next button | `profile_editor__next_button` | Line 1779-1787 | 🔴 CRITICAL |
|
|
| Cancel button | `profile_editor__cancel_button` | Line 1791-1797 | 🔴 CRITICAL |
|
|
| Save button | `profile_editor__save_button` | Line 1798-1814 | 🔴 CRITICAL |
|
|
|
|
**Implementation:**
|
|
```jsx
|
|
<button
|
|
type="submit"
|
|
disabled={loading || loadingStudent}
|
|
data-testid="profile_editor__save_button"
|
|
className={...}
|
|
>
|
|
Save
|
|
</button>
|
|
```
|
|
|
|
---
|
|
|
|
## 📚 **PART 2: MANDATORY PASSWORD RESET MODAL**
|
|
|
|
**File:** `src/pages/designs/design-1/components/MandatoryPasswordResetModal.jsx`
|
|
**Scope:** `mandatory_reset`
|
|
**Total Attributes:** 14
|
|
|
|
---
|
|
|
|
### **2.1 MODAL CONTAINER**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Modal Overlay | `mandatory_reset__modal` | Line 150 | 🔴 CRITICAL |
|
|
| Modal Content | `mandatory_reset__modal_content` | Line 156 | 🟢 OPTIONAL |
|
|
|
|
**Implementation (Line 150):**
|
|
```jsx
|
|
<motion.div
|
|
className="fixed inset-0 bg-black/60 z-[99999] flex items-center justify-center p-4"
|
|
data-testid="mandatory_reset__modal"
|
|
>
|
|
<motion.div
|
|
className="bg-white dark:bg-slate-800 rounded-3xl shadow-2xl max-w-lg w-full relative border border-white/20 dark:border-gray-700"
|
|
data-testid="mandatory_reset__modal_content"
|
|
>
|
|
```
|
|
|
|
---
|
|
|
|
### **2.2 STEP 1: WELCOME SCREEN**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Continue Button | `mandatory_reset__continue_button` | Line 248 | 🔴 CRITICAL |
|
|
|
|
**Implementation (Line 248):**
|
|
```jsx
|
|
<motion.button
|
|
onClick={goToStep2}
|
|
className="w-full mt-6 bg-gradient-to-r from-blue-500 to-indigo-600..."
|
|
data-testid="mandatory_reset__continue_button"
|
|
>
|
|
<span>Continue to Reset Password</span>
|
|
<ArrowRight className="w-5 h-5" />
|
|
</motion.button>
|
|
```
|
|
|
|
---
|
|
|
|
### **2.3 STEP 2: PASSWORD RESET FORM**
|
|
|
|
| Element | Required Attribute | Line Reference | Priority |
|
|
|---------|-------------------|----------------|----------|
|
|
| Form Container | `mandatory_reset__form` | Line 283 | 🔴 CRITICAL |
|
|
| Current Password Input | `mandatory_reset__current_password_input` | Line 290 | 🔴 CRITICAL |
|
|
| Current Password Toggle | `mandatory_reset__current_password_toggle` | Line 305 | 🟢 OPTIONAL |
|
|
| Current Password Error | `mandatory_reset__current_password_error` | Line 313 | 🟡 IMPORTANT |
|
|
| New Password Input | `mandatory_reset__new_password_input` | Line 325 | 🔴 CRITICAL |
|
|
| New Password Toggle | `mandatory_reset__new_password_toggle` | Line 340 | 🟢 OPTIONAL |
|
|
| New Password Error | `mandatory_reset__new_password_error` | Line 348 | 🟡 IMPORTANT |
|
|
| Confirm Password Input | `mandatory_reset__confirm_password_input` | Line 360 | 🔴 CRITICAL |
|
|
| Confirm Password Toggle | `mandatory_reset__confirm_password_toggle` | Line 375 | 🟢 OPTIONAL |
|
|
| Confirm Password Error | `mandatory_reset__confirm_password_error` | Line 383 | 🟡 IMPORTANT |
|
|
| Back Button | `mandatory_reset__back_button` | Line 454 | 🟡 IMPORTANT |
|
|
| Submit Button | `mandatory_reset__submit_button` | Line 464 | 🔴 CRITICAL |
|
|
|
|
**Implementation Examples:**
|
|
|
|
**Form (Line 283):**
|
|
```jsx
|
|
<form onSubmit={handleSubmit} className="p-6 space-y-4" data-testid="mandatory_reset__form">
|
|
```
|
|
|
|
**Current Password Input (Line 290):**
|
|
```jsx
|
|
<input
|
|
type={showCurrentPassword ? 'text' : 'password'}
|
|
name="currentPassword"
|
|
value={formData.currentPassword}
|
|
onChange={handleInputChange}
|
|
data-testid="mandatory_reset__current_password_input"
|
|
className={...}
|
|
/>
|
|
```
|
|
|
|
**Current Password Toggle (Line 305):**
|
|
```jsx
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
|
|
data-testid="mandatory_reset__current_password_toggle"
|
|
className={...}
|
|
>
|
|
```
|
|
|
|
**Current Password Error (Line 313):**
|
|
```jsx
|
|
{errors.currentPassword && (
|
|
<p className="mt-1 text-sm text-red-600 dark:text-red-400 flex items-center gap-1"
|
|
data-testid="mandatory_reset__current_password_error">
|
|
<AlertCircle className="w-4 h-4" />
|
|
{errors.currentPassword}
|
|
</p>
|
|
)}
|
|
```
|
|
|
|
**Submit Button (Line 464):**
|
|
```jsx
|
|
<motion.button
|
|
type="submit"
|
|
disabled={isLoading}
|
|
data-testid="mandatory_reset__submit_button"
|
|
className={...}
|
|
>
|
|
{isLoading ? (
|
|
<>Resetting...</>
|
|
) : (
|
|
<>
|
|
<Lock className="w-5 h-5" />
|
|
Reset Password
|
|
</>
|
|
)}
|
|
</motion.button>
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 **IMPLEMENTATION GUIDE**
|
|
|
|
### **Step 1: Add formatTestId Helper Function**
|
|
|
|
Add this function at the top of `StudentProfileEditor.jsx` (after imports, around line 23):
|
|
|
|
```javascript
|
|
// Helper function to format test IDs
|
|
const formatTestId = (value = '') => {
|
|
return value
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '_') // Replace all non-alphanumeric with underscore
|
|
.replace(/^_|_$/g, '') // Remove leading/trailing underscores
|
|
}
|
|
```
|
|
|
|
### **Step 2: Update Tab Buttons**
|
|
|
|
Update the tab button rendering (Line 1703 in StudentProfileEditor.jsx):
|
|
|
|
```jsx
|
|
<button
|
|
key={idx}
|
|
onClick={() => setActiveTab(idx)}
|
|
data-testid={`profile_editor__tab_${formatTestId(section.title)}`}
|
|
className={...}
|
|
>
|
|
```
|
|
|
|
### **Step 3: Update MultiSelectPicker Component**
|
|
|
|
Update `MultiSelectPicker` component (Line 174-186) to accept and use `testIdPrefix` prop:
|
|
|
|
```jsx
|
|
const MultiSelectPicker = ({ options, selectedItems, onToggle, maxItems, icon: Icon, testIdPrefix }) => {
|
|
// ... existing code ...
|
|
|
|
return (
|
|
<div className="space-y-2 xs:space-y-3">
|
|
<div className="grid grid-cols-1 xs:grid-cols-2 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
|
{options.map((option) => {
|
|
// ... existing code ...
|
|
return (
|
|
<label key={option} className={...}>
|
|
<input
|
|
type="checkbox"
|
|
checked={isSelected}
|
|
disabled={isDisabled}
|
|
onChange={...}
|
|
data-testid={testIdPrefix ? `${testIdPrefix}__${formatTestId(option)}` : undefined}
|
|
className={...}
|
|
/>
|
|
{/* ... */}
|
|
</label>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
### **Step 4: Add data-testid to All Input Elements**
|
|
|
|
For each `<input>`, `<select>`, `<textarea>`, add `data-testid` attribute:
|
|
|
|
```jsx
|
|
<input
|
|
type="text"
|
|
value={form.firstName}
|
|
onChange={(e) => handleFieldChange('firstName', e.target.value)}
|
|
data-testid="profile_editor__first_name_input"
|
|
className={...}
|
|
/>
|
|
```
|
|
|
|
### **Step 5: Add data-testid to All Buttons**
|
|
|
|
For each `<button>`, add `data-testid` attribute:
|
|
|
|
```jsx
|
|
<button
|
|
type="submit"
|
|
disabled={loading || loadingStudent}
|
|
data-testid="profile_editor__save_button"
|
|
className={...}
|
|
>
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ **VERIFICATION CHECKLIST**
|
|
|
|
After implementation, verify:
|
|
|
|
### **Profile Editor:**
|
|
- [ ] All 9 tab buttons have `data-testid` attributes
|
|
- [ ] All input fields have `data-testid` attributes
|
|
- [ ] All select dropdowns have `data-testid` attributes
|
|
- [ ] All textareas have `data-testid` attributes
|
|
- [ ] All checkboxes have `data-testid` attributes
|
|
- [ ] All buttons (Save, Cancel, Prev, Next, Back, Scroll) have `data-testid` attributes
|
|
- [ ] All MultiSelectPicker checkboxes have `data-testid` attributes
|
|
- [ ] All "Others" text inputs have `data-testid` attributes
|
|
- [ ] Progress value display has `data-testid` attribute
|
|
- [ ] Missing fields toggle has `data-testid` attribute
|
|
- [ ] Page container has `data-testid` attribute
|
|
|
|
### **Password Reset Modal:**
|
|
- [ ] Modal overlay has `data-testid="mandatory_reset__modal"`
|
|
- [ ] Continue button has `data-testid="mandatory_reset__continue_button"`
|
|
- [ ] Form has `data-testid="mandatory_reset__form"`
|
|
- [ ] All 3 password inputs have their data-testid attributes
|
|
- [ ] All 3 error messages have their data-testid attributes
|
|
- [ ] Back button has `data-testid="mandatory_reset__back_button"`
|
|
- [ ] Submit button has `data-testid="mandatory_reset__submit_button"`
|
|
|
|
---
|
|
|
|
## 🧪 **VERIFICATION SCRIPT**
|
|
|
|
After implementation, run this in browser console to verify:
|
|
|
|
```javascript
|
|
// Check Profile Editor attributes
|
|
const profileEditorIds = Array.from(document.querySelectorAll('[data-testid^="profile_editor__"]'))
|
|
.map(el => el.getAttribute('data-testid'))
|
|
.sort()
|
|
|
|
console.log(`✅ Profile Editor: Found ${profileEditorIds.length} data-testid attributes`)
|
|
|
|
// Check Password Reset Modal attributes
|
|
const mandatoryResetIds = Array.from(document.querySelectorAll('[data-testid^="mandatory_reset__"]'))
|
|
.map(el => el.getAttribute('data-testid'))
|
|
.sort()
|
|
|
|
console.log(`✅ Password Reset Modal: Found ${mandatoryResetIds.length} data-testid attributes`)
|
|
|
|
// Check for missing critical attributes
|
|
const criticalProfileEditor = [
|
|
'profile_editor__page',
|
|
'profile_editor__progress_value',
|
|
'profile_editor__save_button',
|
|
'profile_editor__tab_personal_information',
|
|
'profile_editor__first_name_input',
|
|
'profile_editor__email_input',
|
|
]
|
|
|
|
const criticalMandatoryReset = [
|
|
'mandatory_reset__modal',
|
|
'mandatory_reset__continue_button',
|
|
'mandatory_reset__form',
|
|
'mandatory_reset__current_password_input',
|
|
'mandatory_reset__new_password_input',
|
|
'mandatory_reset__submit_button',
|
|
]
|
|
|
|
const missingProfileEditor = criticalProfileEditor.filter(id => !profileEditorIds.includes(id))
|
|
const missingMandatoryReset = criticalMandatoryReset.filter(id => !mandatoryResetIds.includes(id))
|
|
|
|
if (missingProfileEditor.length > 0) {
|
|
console.error('❌ Missing Profile Editor attributes:', missingProfileEditor)
|
|
} else {
|
|
console.log('✅ All critical Profile Editor attributes present!')
|
|
}
|
|
|
|
if (missingMandatoryReset.length > 0) {
|
|
console.error('❌ Missing Password Reset Modal attributes:', missingMandatoryReset)
|
|
} else {
|
|
console.log('✅ All critical Password Reset Modal attributes present!')
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 **PRIORITY ORDER**
|
|
|
|
### **🔴 CRITICAL (Must Have - Implement First):**
|
|
|
|
**Profile Editor:**
|
|
1. Tab buttons (all 9 tabs)
|
|
2. Save, Cancel, Prev, Next buttons
|
|
3. All input fields in Personal Information
|
|
4. All input fields in Contact Information
|
|
5. Progress value display
|
|
6. All input fields in Parent/Guardian
|
|
7. All input fields in Education Details
|
|
8. All checkboxes in Focus Areas
|
|
9. All checkboxes in Self-Assessment
|
|
10. All checkboxes in Hobbies & Clubs
|
|
11. All textareas in Achievements
|
|
12. All checkboxes in Expectations
|
|
|
|
**Password Reset Modal:**
|
|
1. Modal overlay
|
|
2. Continue button
|
|
3. Form container
|
|
4. All 3 password inputs
|
|
5. Submit button
|
|
|
|
### **🟡 IMPORTANT (Should Have - Implement Second):**
|
|
|
|
**Profile Editor:**
|
|
- Missing fields toggle
|
|
- Back button
|
|
- Tab scroll buttons
|
|
- All "Others" text inputs
|
|
- Conditional fields (guardian, specially abled details)
|
|
|
|
**Password Reset Modal:**
|
|
- Back button
|
|
- All 3 error messages
|
|
|
|
### **🟢 OPTIONAL (Nice to Have - Implement Last):**
|
|
|
|
**Profile Editor:**
|
|
- Page container
|
|
- Modal content container
|
|
|
|
**Password Reset Modal:**
|
|
- Modal content container
|
|
- Password toggle buttons
|
|
|
|
---
|
|
|
|
## 📊 **SUMMARY STATISTICS**
|
|
|
|
| Component | Total Attributes | Critical | Important | Optional |
|
|
|-----------|-----------------|----------|-----------|----------|
|
|
| **Profile Editor** | ~200+ | ~150 | ~40 | ~10 |
|
|
| **Password Reset Modal** | 14 | 7 | 4 | 3 |
|
|
| **TOTAL** | **~214+** | **~157** | **~44** | **~13** |
|
|
|
|
---
|
|
|
|
## 📝 **FILES TO UPDATE**
|
|
|
|
1. **`src/pages/StudentProfileEditor.jsx`**
|
|
- Add `formatTestId` function
|
|
- Add `data-testid` to all elements listed above
|
|
- Update `MultiSelectPicker` component
|
|
|
|
2. **`src/pages/designs/design-1/components/MandatoryPasswordResetModal.jsx`**
|
|
- Add `data-testid` to all elements listed above
|
|
|
|
---
|
|
|
|
## 🚀 **AFTER IMPLEMENTATION**
|
|
|
|
Once all attributes are added:
|
|
|
|
1. **Run Verification Script** (see above) in browser console
|
|
2. **Share Results** with Automation Team
|
|
3. **Automation Team** will:
|
|
- Update locators to use data-testid
|
|
- Run DOM Inspector to verify
|
|
- Run full test suite
|
|
- Confirm 100% reliability
|
|
|
|
**Expected Results:**
|
|
- ✅ Tests run in < 1 minute (currently 8+ minutes)
|
|
- ✅ 100% test pass rate
|
|
- ✅ Zero fragile XPath/CSS selectors needed
|
|
- ✅ World-class automation reliability
|
|
|
|
---
|
|
|
|
## 📞 **SUPPORT & QUESTIONS**
|
|
|
|
If you have questions about:
|
|
- Naming conventions
|
|
- Implementation details
|
|
- Testing requirements
|
|
- Verification process
|
|
|
|
**Contact:** Automation Team
|
|
|
|
---
|
|
|
|
## ✅ **FINAL CHECKLIST**
|
|
|
|
Before marking as complete:
|
|
|
|
- [ ] All Profile Editor attributes added
|
|
- [ ] All Password Reset Modal attributes added
|
|
- [ ] formatTestId function added
|
|
- [ ] MultiSelectPicker updated with testIdPrefix
|
|
- [ ] Verification script run successfully
|
|
- [ ] Results shared with Automation Team
|
|
- [ ] Automation Team confirmed implementation
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** 2025-01-20
|
|
**Status:** ✅ Ready for UI Team Implementation
|
|
**Total Attributes Required:** ~214+
|
|
|
|
---
|
|
|
|
**This is a STANDALONE document - contains everything the UI team needs!**
|
|
|
|
|