""" DOM Inspector - World-Class Debug Tool Purpose: Inspect actual DOM structure at runtime to identify correct locators Usage: Run this script to quickly identify element structures without running full tests This saves time by: 1. Inspecting DOM directly without full test execution 2. Testing multiple locator strategies quickly 3. Identifying correct selectors before updating code 4. Verifying element presence and visibility """ import sys import os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from pages.login_page import LoginPage from pages.mandatory_reset_page import MandatoryResetPage from config.config import TEST_USERNAME, TEST_PASSWORD, BASE_URL import time import json class DOMInspector: """World-Class DOM Inspector for Quick Debugging""" def __init__(self, driver): self.driver = driver def find_elements_by_strategies(self, element_name, strategies): """ Try multiple locator strategies and report results Args: element_name: Name of element for logging strategies: List of (strategy_name, locator) tuples """ print(f"\n{'='*80}") print(f"πŸ” INSPECTING: {element_name}") print(f"{'='*80}") results = [] for strategy_name, locator in strategies: try: if isinstance(locator, tuple): by_type, selector = locator else: by_type, selector = locator[0], locator[1] print(f"\nπŸ“‹ Strategy: {strategy_name}") print(f" Locator: {by_type} = '{selector}'") # Try to find element elements = self.driver.find_elements(by_type, selector) if elements: print(f" βœ… Found {len(elements)} element(s)") for idx, elem in enumerate(elements): try: is_displayed = elem.is_displayed() is_enabled = elem.is_enabled() if hasattr(elem, 'is_enabled') else 'N/A' tag_name = elem.tag_name text = elem.text[:100] if elem.text else 'No text' # Get attributes attrs = {} try: attrs['id'] = elem.get_attribute('id') attrs['class'] = elem.get_attribute('class') attrs['data-testid'] = elem.get_attribute('data-testid') attrs['name'] = elem.get_attribute('name') attrs['type'] = elem.get_attribute('type') except: pass print(f" Element {idx + 1}:") print(f" - Tag: {tag_name}") print(f" - Displayed: {is_displayed}") print(f" - Enabled: {is_enabled}") print(f" - Text: {text}") print(f" - Attributes: {json.dumps({k: v for k, v in attrs.items() if v}, indent=8)}") # Get outer HTML snippet try: outer_html = elem.get_attribute('outerHTML') if outer_html: snippet = outer_html[:200] + '...' if len(outer_html) > 200 else outer_html print(f" - HTML: {snippet}") except: pass results.append({ 'strategy': strategy_name, 'locator': selector, 'found': True, 'displayed': is_displayed, 'element': elem, 'attributes': attrs }) except Exception as e: print(f" ⚠️ Error inspecting element {idx + 1}: {e}") else: print(f" ❌ No elements found") results.append({ 'strategy': strategy_name, 'locator': selector, 'found': False }) except Exception as e: print(f" ❌ Error with strategy: {e}") results.append({ 'strategy': strategy_name, 'locator': selector, 'found': False, 'error': str(e) }) return results def inspect_modal_structure(self): """Inspect password reset modal structure""" print(f"\n{'='*80}") print("πŸ” INSPECTING: Password Reset Modal Structure") print(f"{'='*80}") # Check for modal overlay print("\nπŸ“‹ Checking for modal overlay...") overlay_selectors = [ ("CSS - Exact", (By.CSS_SELECTOR, "div.fixed.inset-0.bg-black\\/60.z-\\[99999\\]")), ("CSS - Partial", (By.CSS_SELECTOR, "div[class*='fixed'][class*='inset-0'][class*='bg-black'][class*='z-[99999]']")), ("CSS - Generic", (By.CSS_SELECTOR, "div.fixed.inset-0.bg-black")), ("XPath - Fixed inset", (By.XPATH, "//div[contains(@class, 'fixed') and contains(@class, 'inset-0')]")), ] overlay_results = self.find_elements_by_strategies("Modal Overlay", overlay_selectors) # Check for modal content print("\nπŸ“‹ Checking for modal content...") content_selectors = [ ("Text - Welcome", (By.XPATH, "//*[contains(text(), 'Welcome to Cognitive Prism')]")), ("Text - Reset Password", (By.XPATH, "//*[contains(text(), 'Password Reset Required')]")), ("Text - Secure Account", (By.XPATH, "//*[contains(text(), 'Secure Your Account')]")), ] content_results = self.find_elements_by_strategies("Modal Content", content_selectors) return overlay_results, content_results def inspect_continue_button(self): """Inspect Continue button structure""" print(f"\n{'='*80}") print("πŸ” INSPECTING: Continue Button") print(f"{'='*80}") strategies = [ ("data-testid", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__continue_button']")), ("XPath - Span text", (By.XPATH, "//span[contains(text(), 'Continue to Reset Password')]")), ("XPath - Button with span", (By.XPATH, "//button[.//span[contains(text(), 'Continue')]]")), ("XPath - Button contains Continue", (By.XPATH, "//button[contains(., 'Continue')]")), ("XPath - Button with Reset", (By.XPATH, "//button[contains(., 'Reset Password')]")), ("XPath - Any button in modal", (By.XPATH, "//div[contains(@class, 'fixed')]//button")), ("XPath - Button with arrow icon", (By.XPATH, "//button[.//*[local-name()='svg']]")), ] return self.find_elements_by_strategies("Continue Button", strategies) def inspect_form_fields(self): """Inspect password reset form fields""" print(f"\n{'='*80}") print("πŸ” INSPECTING: Password Reset Form Fields") print(f"{'='*80}") strategies = [ ("Form container", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__form']")), ("Current password input", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__current_password_input']")), ("New password input", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__new_password_input']")), ("Confirm password input", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__confirm_password_input']")), ("Submit button", (By.CSS_SELECTOR, "[data-testid='mandatory_reset__submit_button']")), ("XPath - Input by name", (By.XPATH, "//input[@name='currentPassword' or @name='newPassword' or @name='confirmPassword']")), ("XPath - Input type password", (By.XPATH, "//input[@type='password']")), ] return self.find_elements_by_strategies("Form Fields", strategies) def get_page_source_snippet(self, search_text, context_lines=5): """Get snippet of page source around specific text""" try: page_source = self.driver.page_source if search_text.lower() in page_source.lower(): index = page_source.lower().index(search_text.lower()) start = max(0, index - 500) end = min(len(page_source), index + 500) snippet = page_source[start:end] return snippet return None except: return None def inspect_page_source(self): """Inspect page source for key indicators""" print(f"\n{'='*80}") print("πŸ” INSPECTING: Page Source Indicators") print(f"{'='*80}") indicators = [ "Welcome to Cognitive Prism", "Password Reset Required", "Continue to Reset Password", "mandatory_reset", "data-testid", ] page_source = self.driver.page_source.lower() for indicator in indicators: found = indicator.lower() in page_source status = "βœ…" if found else "❌" print(f"{status} '{indicator}': {'Found' if found else 'Not found'}") if found: snippet = self.get_page_source_snippet(indicator) if snippet: print(f" Context: {snippet[:300]}...") def debug_password_reset_modal(): """Main debug function for password reset modal""" print("=" * 80) print("πŸ” DOM INSPECTOR - Password Reset Modal Debug") print("=" * 80) print("\n🎯 Purpose: Inspect actual DOM structure to identify correct locators") print("πŸ’‘ This saves time by avoiding full test execution\n") # Setup Chrome driver chrome_options = Options() chrome_options.add_argument("--start-maximized") chrome_options.add_argument("--disable-blink-features=AutomationControlled") chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option('useAutomationExtension', False) driver = webdriver.Chrome(options=chrome_options) inspector = DOMInspector(driver) try: # Step 1: Login print(f"\n{'='*80}") print("STEP 1: LOGIN") print(f"{'='*80}") login_page = LoginPage(driver) login_page.login(identifier=TEST_USERNAME, password=TEST_PASSWORD) print(f"βœ… Login completed") print(f" Current URL: {driver.current_url}") time.sleep(2) # Step 2: Inspect modal structure print(f"\n{'='*80}") print("STEP 2: INSPECT MODAL STRUCTURE") print(f"{'='*80}") overlay_results, content_results = inspector.inspect_modal_structure() # Step 3: Inspect Continue button print(f"\n{'='*80}") print("STEP 3: INSPECT CONTINUE BUTTON") print(f"{'='*80}") continue_results = inspector.inspect_continue_button() # Step 4: Inspect form fields (if form is visible) print(f"\n{'='*80}") print("STEP 4: INSPECT FORM FIELDS") print(f"{'='*80}") form_results = inspector.inspect_form_fields() # Step 5: Inspect page source inspector.inspect_page_source() # Step 6: Summary and recommendations print(f"\n{'='*80}") print("πŸ“Š SUMMARY & RECOMMENDATIONS") print(f"{'='*80}") # Find working strategies working_overlay = [r for r in overlay_results if r.get('found') and r.get('displayed')] working_continue = [r for r in continue_results if r.get('found') and r.get('displayed')] working_form = [r for r in form_results if r.get('found') and r.get('displayed')] print(f"\nβœ… Working Strategies Found:") if working_overlay: print(f" Modal Overlay: {working_overlay[0]['strategy']} - {working_overlay[0]['locator']}") if working_continue: print(f" Continue Button: {working_continue[0]['strategy']} - {working_continue[0]['locator']}") if working_form: print(f" Form Fields: {working_form[0]['strategy']} - {working_form[0]['locator']}") if not working_continue: print(f"\n⚠️ Continue Button Not Found!") print(f" Recommendations:") print(f" 1. Check if button is inside a shadow DOM") print(f" 2. Check if button has animation delays") print(f" 3. Try JavaScript-based element finding") print(f" 4. Check if button is inside a specific container") print(f"\n⏸️ Browser will stay open for 30 seconds for manual inspection...") print(f" You can inspect the DOM manually in browser DevTools") time.sleep(30) except Exception as e: print(f"\n❌ ERROR: {e}") import traceback traceback.print_exc() print(f"\n⏸️ Browser will stay open for 30 seconds for manual inspection...") time.sleep(30) finally: print(f"\n{'='*80}") print("CLEANUP") print(f"{'='*80}") driver.quit() print("βœ… Driver closed") if __name__ == "__main__": debug_password_reset_modal()