התמודדות עם Shadow DOM באמצעות סלניום אילור שורר

Shadow DOM הוא מושג שהתחיל להיכנס לעולם פיתוח ה-Web בסביבות 2011, ונועד להתמודד עם בעיה נפוצה - כאשר מוסיפים אלמנטים לדף באופן דינמי (בעזרת JS), אנחנו עלולים ליצור התנגשויות עם הגדרות אחרות בדף - אולי יש אלמנטים אחרים עם השם הזה, או שאחת מהגדרות ה-CSS הגלובליות תשפיע על איך שהרכיבים שלנו נראים באופן שונה מזה שרצינו. כדי לפתור את זה, נוספה האפשרות ליצור תת-עץ נפרד מההגדרות האחרות בדף - אנחנו לא נשפיע על הדף החיצוני והוא לא ישפיע עלינו. כשאנחנו בונים אתר, ובמיוחד כשאנחנו בונים ספריית JS שצריכה לייצר לעצמה רכיבים בלי ידע מוקדם על הדף - זה ממש נוח. אבל כשאנחנו מגיעים לבדוק את הכל, נגלה שההפרדה הזו מקשה על הכלים האוטומטיים לגשת לחלקים האלה. במאמר הזה נבין מהם האתגרים, ונציג מספר דרכים להתמודדות עם אתגרים אלו. 

 

למה קשה כל כך לעבוד עםShadow DOM?

 Shadow DOM  מתנהג כעץ נסתר ונפרד המקושר לאלמנט "אבא", ומגן על המבנה הפנימי והעיצוב שלו מה- DOM החיצוני ובכך מונע השפעה של CSS או קוד JavaScript על הקומפוננטה שלו, מה שמאפשר בעצם יצירת רכיבים הניתנים לשימוש חוזר עם פונקציונליות ועיצוב משלהם ללא השפעה חיצונית.

תצלום דף המכיל בתוכו תתי עצים – Shadow DOM

כאשר במערכת שעליה אנו מבצעים אוטומציה מוטמעים Shadow DOMS, ביצוע תהליכי אוטומציה על Shadow DOM באמצעות סלניום וגישה לאלמנטים בתוכו הינו תהליך מעט יותר מורכב מגישה לאלמנטים ב DOM "הרגיל" - מאחר ו-Shadow DOM אינו נגיש באופן ישיר למתודות הרגילות של סלניום.

קיימות שתי דרכים לגשת לאלמנטים אלו:

1. באמצעות המתודה execute_script()

2. בעזרת גישה לתכונה shadow_root - זמין רק מגרסת סלניום 4.0

לפני שנציג את המימוש של דרכים אלו באמצעות קוד, נעבור על העקרונות שמאחוריהן:

1. מציאת ה-entry point של ה-Shadow DOM – על מנת לבצע אינטראקציה עם אלמנטים בתוך ה-Shadow DOM צריך למצוא את אלמנט ה"אבא" שלו.

2. שימוש ב-Shadow DOM בתור הדרייבר לביצוע אינטראקציה על אלמנטים בתוכו –

ברגע שהשגנו את האלמנט האבא שהוא בעצם "השורש" של ה-Shadow DOM אנחנו נשתמש בו בתור הדרייבר כדי לנווט ולקיים אינטראקציה עם האלמנטים בתוך ה-Shadow DOM,

מה שמאפשר לנו לבצע פעולות כגון מציאת אלמנטים, לחיצה על כפתורים וכן הלאה.

3. שימוש במזהה CSS_SELECTOR בלבד. נכון לכתיבת מדריך זה – CSS_SELECTOR הינו המזהה היחיד הנתמך לאינטראקציה עם אלמנטים בתוך ה-Shadow DOM.

הנה דוגמאות קוד (Python) לשתי הדרכים באמצעותן ניתן לגשת לאלמנטים בתוך ה-Shadow DOM:

1. באמצעות המתודה

execute_script():

#  Execute JavaScript to get the shadow root

shadow_root_script = "return document.querySelector('#shadow-root-wrapper').shadowRoot"

shadow_root = driver.execute_script(shadow_root_script)

# Find an element within the shadow root using CSS selector

element_in_shadow_dom = shadow_root.find_element(By.CSS_SELECTOR, '...')

2. בסלניום 4 נוספה תמיכה לגישה ישירה לאלמנטים בתוך ה-Shadow DOM באמצעות

התכונה `shadow_root`:

#  Find the element with the shadow DOM

shadow_root_wrapper = driver.find_element(By.CSS_SELECTOR, '#shadow-root-wrapper')

#  Access the shadow root of the element

shadow_root = shadow_root_wrapper.shadow_root

# Find an element within the shadow root using CSS selector

element_in_shadow_dom = shadow_root.find_element(By.CSS_SELECTOR, '...')

על ידי שימוש באחת מהשיטות הללו, אנו יכולים לגשת ולאלמנטים בתוך Shadow DOM באמצעות סלניום.

טיפ נחמד:

כאשר מתמודדים עם DOM שכולל הרבה Shadow DOMS מקוננים (תתי עצים), הדרך הטובה ביותר למצוא את נתיב של האלמנט הרצוי היא באמצעות שימוש בכלי המפתחים של הדפדפן לדוגמא בכרום:

Right click on the element > Copy > Copy js path

לסיכום

ה-Shadow DOM  מביא יכולות "הכלה"  ותיחום לרכיבי אינטרנט, מאפשר ארגון קוד טוב יותר, שימוש חוזר, והגנה מפני השפעה של CSS  או קוד JavaScript חיצוני. למרות שגישה לאלמנטים בתוך  Shadow DOM  באמצעות סלניום יכולה להיות מאתגרת, סלניום מספק דרכים לעקיפת הבעיה באמצעות ביצוע JavaScript ותמיכה ישירה בסלניום 4. בעזרת טכניקות אלו, אנחנו כמפתחי אוטומציה יכולים להתמודד בהצלחה עם רכיבי Shadow DOM באמצעות סלניום מה שמאפשר בדיקה יעילה של רכיבי אינטרנט המממשים טכנולוגיה זו.