WebDriver क्लिक () बनाम जावास्क्रिप्ट क्लिक ()


126

कहानी:

यहां StackOverflow पर, मैंने उपयोगकर्ताओं को यह रिपोर्ट करते हुए देखा है कि वे सेलेनियम वेबड्राइवर "क्लिक" कमांड के माध्यम से एक तत्व को क्लिक नहीं कर सकते हैं और स्क्रिप्ट निष्पादित करके जावास्क्रिप्ट क्लिक के साथ इसके चारों ओर काम कर सकते हैं।

पायथन में उदाहरण:

element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)

WebDriverJS / प्रोटेक्टर में उदाहरण:

var elm = $("#myid");
browser.executeScript("arguments[0].click();", elm.getWebElement());

प्रश्न:

जब एक नियमित वेबड्राइवर क्लिक नहीं करता है तो "जावास्क्रिप्ट के माध्यम से" काम क्यों करता है? जब वास्तव में ऐसा हो रहा है और इस वर्कअराउंड (यदि कोई हो) के नकारात्मक पक्ष क्या है?

मैंने व्यक्तिगत रूप से इस वर्कअराउंड का उपयोग पूरी तरह से समझे बिना किया है कि मुझे यह क्यों करना है और इससे क्या समस्याएं हो सकती हैं।

जवाबों:


150

इसके विपरीत जो वर्तमान में स्वीकार किए गए उत्तर का सुझाव देता है, वहाँ PhantomJS के लिए कुछ भी विशिष्ट नहीं है, जब वेबड्राइवर को क्लिक करने और इसे जावास्क्रिप्ट में करने के बीच अंतर आता है।

अंतर

दो तरीकों के बीच आवश्यक अंतर सभी ब्राउज़रों के लिए सामान्य है और इसे बहुत सरल रूप से समझाया जा सकता है:

  • WebDriver: जब WebDriver क्लिक करता है, तो यह सबसे अच्छा प्रयास करता है कि जब कोई वास्तविक उपयोगकर्ता ब्राउज़र का उपयोग करता है तो वह क्या कर सकता है। "पर क्लिक करें मुझे" मान लीजिए आप एक तत्व एक जो कि एक बटन का कहना है है और एक तत्व बी जो एक है divतत्व है जो पारदर्शी है, लेकिन इसके आयाम हैं और zIndexइसलिए सेट है कि यह पूरी तरह से फिर ए को शामिल किया गया आप WebDriver बता क्लिक करने के लिए ए WebDriver इच्छा क्लिक का अनुकरण करें ताकि B को पहले क्लिक प्राप्त हो । क्यों? चूँकि B A को कवर करता है, और यदि कोई उपयोगकर्ता A पर क्लिक करने का प्रयास करता है, तो B को घटना पहले मिल जाएगी। A को आखिरकार क्लिक इवेंट मिलेगा या नहीं यह इस बात पर निर्भर करता है कि B कैसे इवेंट को हैंडल करता है। किसी भी दर पर, इस मामले में WebDriver के साथ व्यवहार वैसा ही होता है जब कोई वास्तविक उपयोगकर्ता A पर क्लिक करने का प्रयास करता है।

  • जावास्क्रिप्ट: अब, मान लीजिए कि आप जावास्क्रिप्ट का उपयोग करते हैं A.click()क्लिक करने की यह विधि वास्तव में तब नहीं होती है जब उपयोगकर्ता ए पर क्लिक करने की कोशिश करता है। जावास्क्रिप्ट clickसीधे को घटना भेजता है , और बी को कोई भी घटना नहीं मिलेगी।

क्यों एक जावास्क्रिप्ट क्लिक काम करता है जब एक वेबड्राइवर क्लिक करता है न?

जैसा कि मैंने ऊपर WebDriver का अनुकरण करने की कोशिश की है कि जब कोई वास्तविक उपयोगकर्ता किसी ब्राउज़र का उपयोग कर रहा होता है तो यह सबसे अच्छा होगा। इस तथ्य का तथ्य यह है कि DOM में ऐसे तत्व हो सकते हैं जो उपयोगकर्ता के साथ बातचीत नहीं कर सकता है, और WebDriver आपको इन तत्वों पर क्लिक करने की अनुमति नहीं देगा। मैंने जिस ओवरलैपिंग मामले का उल्लेख किया है, इसके अलावा, यह भी जोर देता है कि अदृश्य तत्वों को क्लिक नहीं किया जा सकता है। एक सामान्य मामला जिसे मैं स्टैक ओवरफ्लो प्रश्नों में देखता हूं, वह है जो एक GUI तत्व के साथ बातचीत करने की कोशिश कर रहा है जो पहले से ही DOM में मौजूद है, लेकिन केवल तभी दिखाई देता है जब किसी अन्य तत्व में हेरफेर किया गया हो। यह कभी-कभी ड्रॉपडाउन मेनू के साथ होता है: आपको सबसे पहले बटन पर क्लिक करना होता है और ड्रॉपडाउन से पहले मेनू आइटम का चयन किया जा सकता है। यदि कोई मेनू दिखाई देने से पहले मेनू आइटम पर क्लिक करने का प्रयास करता है,यदि व्यक्ति इसे जावास्क्रिप्ट के साथ करने की कोशिश करता है, तो यह काम करेगा क्योंकि घटना सीधे तत्व को वितरित की जाती है, भले ही दृश्यता के बावजूद।

जब आप क्लिक करने के लिए जावास्क्रिप्ट का उपयोग करना चाहिए?

यदि आप किसी एप्लिकेशन के परीक्षण के लिए सेलेनियम का उपयोग कर रहे हैं , तो इस प्रश्न का मेरा उत्तर "लगभग कभी नहीं" है। द्वारा और बड़े, आपके सेलेनियम परीक्षण को पुन: पेश करना चाहिए कि उपयोगकर्ता ब्राउज़र के साथ क्या करेगा। ड्रॉप डाउन मेनू का उदाहरण लेते हुए: एक परीक्षण बटन पर क्लिक करना चाहिए जो पहले ड्रॉप डाउन लाता है, और फिर मेनू आइटम पर क्लिक करें। यदि GUI के साथ कोई समस्या है क्योंकि बटन अदृश्य है, या बटन मेनू आइटम, या कुछ समान दिखाने में विफल रहता है, तो आपका परीक्षण विफल हो जाएगा और आपने बग का पता लगा लिया होगा। यदि आप क्लिक करने के लिए जावास्क्रिप्ट का उपयोग करते हैं, तो आप स्वचालित परीक्षण के माध्यम से इन बगों का पता लगाने में सक्षम नहीं होंगे।

मैं कहता हूं "लगभग कभी नहीं" क्योंकि अपवाद हो सकते हैं जहां यह जावास्क्रिप्ट का उपयोग करने के लिए समझ में आता है। वे बहुत दुर्लभ होना चाहिए, यद्यपि।

यदि आप साइटों को स्क्रैप करने के लिए सेलेनियम का उपयोग कर रहे हैं , तो उपयोगकर्ता के व्यवहार को पुन: पेश करने का प्रयास करना उतना महत्वपूर्ण नहीं है। तो GUI को बायपास करने के लिए JavaScript का उपयोग करना किसी समस्या से कम नहीं है।


1
बहुत बेहतर जवाब, यह स्वीकार किया जाना चाहिए। ऊपर दिया गया उत्तर एक किनारे के मामले की बात कर रहा है जो कि फैंटम जेएस के लिए विशिष्ट है, यह एक बहुत सटीक IMHO है।
आर्देसको

@Ardesco निश्चित रूप से। के रूप में चिह्नित। एकदम सही और काफी विस्तृत जवाब।
एलेक्सी

योजना के अनुसार इनाम को पुरस्कृत करते हुए, लेकिन मैं अभी तक एक और भयानक उत्तर के लिए धन्यवाद देने के लिए एक नई शुरुआत करूंगा। धन्यवाद।
alecxe

1
बहुत अच्छा और बोधगम्य उत्तर। मेरे अनुभव में WebDriver को AngularJS पृष्ठों के साथ बहुत अधिक समस्याएँ हुई हैं: कुछ तत्वों के साथ WebDriver के तरीके clickया sendKeysकाम - लेकिन हमेशा नहीं। कोई भी समस्या या अन्य अपवाद नहीं था, परीक्षण के मामले में आगे कोई प्रगति नहीं हुई। लॉगिंग से पता चला कि कार्रवाई निष्पादित की गई थी। कभी-कभी Actionमदद करते हुए । अगर मैंने मैन्युअल रूप से तत्व पर क्लिक किया (परीक्षण के मामले के बाद रोक दिया गया था), तो सब कुछ ठीक काम किया। इसलिए हमने उस अवसर पर कच्चे जेएस पर स्विच किया। मैंने पिछले 2 वर्षों से AngularJS के साथ काम नहीं किया है, इसलिए चीजें अब बेहतर हो सकती हैं।
वुर्गस्पा

1
@ एलेक्स मेरे पास एक आसान लिंक नहीं है। मेरा उत्तर विशेष रूप से सेलेनियम के साथ अनुभव से लिया गया है, और सामान्य रूप से उपयोगकर्ता घटनाओं का अनुकरण करने के साथ। मैंने 5 साल पहले सेलेनियम का उपयोग करना शुरू कर दिया है। समय के दौरान मैंने सेलेनियम का उपयोग किया है, मुझे कुछ समस्याओं को ठीक करने के लिए सेलेनियम का कोड पढ़ना पड़ा है और मैंने इवेंट डिस्पैचिंग के बारे में कुछ बग रिपोर्ट दर्ज की हैं और सेलेनियम डेवलपर्स के साथ बग पर चर्चा की है। "जितना हो सके उतना अच्छा" लक्ष्य है। मैंने निश्चित रूप से (अब निश्चित) बग का सामना किया है जो इसे उस लक्ष्य तक पहुंचने से रोकता है। कुछ कीड़े रह सकते हैं।
लुई

30

ड्राइवर द्वारा निष्पादित किया गया क्लिक वास्तविक उपयोगकर्ता के व्यवहार को यथासंभव बंद करने की कोशिश करता है, जबकि जावास्क्रिप्ट ईवेंट के HTMLElement.click()लिए डिफ़ॉल्ट कार्रवाई करता है click, भले ही वह तत्व इंटरएक्टिव न हो।

अंतर हैं:

  • ड्राइवर यह सुनिश्चित करता है कि तत्व दृश्य में स्क्रॉल करके दिखाई दे रहा है और जाँचता है कि तत्व इंटरैक्टेबल है

    ड्राइवर एक त्रुटि उठाएगा:

    • जब क्लिक के निर्देशांक में शीर्ष पर मौजूद तत्व लक्षित तत्व या वंशज नहीं है
    • जब तत्व का कोई सकारात्मक आकार नहीं है या यदि वह पूरी तरह से पारदर्शी है
    • जब तत्व एक अक्षम इनपुट या बटन है (विशेषता / संपत्ति disabledहै true)
    • जब तत्व में माउस पॉइंटर अक्षम होता है (CSS pointer-eventsहै none)


    एक जावास्क्रिप्ट HTMLElement.click()हमेशा डिफ़ॉल्ट कार्रवाई करेगा या यदि तत्व अक्षम है तो सबसे अच्छा चुपचाप विफल हो जाएगा।

  • अगर यह ध्यान देने योग्य है, तो ड्राइवर को तत्व को ध्यान में लाने की उम्मीद है।

    एक जावास्क्रिप्ट HTMLElement.click()नहीं होगा

  • ड्राइवर से एक वास्तविक उपयोगकर्ता की तरह सभी घटनाओं (मूसमोव, मूसडाउन, माउसअप, क्लिक, ...) का उत्सर्जन करने की उम्मीद की जाती है ।

    एक जावास्क्रिप्ट HTMLElement.click()केवल clickघटना का उत्सर्जन करता है । पृष्ठ इन अतिरिक्त घटनाओं पर भरोसा कर सकता है और यदि वे उत्सर्जित नहीं होते हैं तो अलग तरह से व्यवहार कर सकते हैं।

    ये Chrome द्वारा एक क्लिक के लिए ड्राइवर द्वारा उत्सर्जित होने वाली घटनाएँ हैं:

    mouseover {target:#topic, clientX:222, clientY:343, isTrusted:true, ... }
    mousemove {target:#topic, clientX:222, clientY:343, isTrusted:true, ... }
    mousedown {target:#topic, clientX:222, clientY:343, isTrusted:true, ... }
    mouseup {target:#topic, clientX:222, clientY:343, isTrusted:true, ... }
    click {target:#topic, clientX:222, clientY:343, isTrusted:true, ... }

    और यह एक जावास्क्रिप्ट इंजेक्शन के साथ उत्सर्जित घटना है:

    click {target:#topic, clientX:0, clientY:0, isTrusted:false, ... }
  • जावास्क्रिप्ट द्वारा उत्सर्जित घटना पर .click() भरोसा नहीं किया जाता है और डिफ़ॉल्ट कार्रवाई को लागू नहीं किया जा सकता है:

    https://developer.mozilla.org/en/docs/Web/API/Event/isTrusted
    https://googlechrome.github.io/samples/event-istrusted/index.html

    ध्यान दें कि कुछ ड्राइवर अभी भी अविश्वसनीय घटनाओं को पैदा कर रहे हैं। यह संस्करण 2.1 के रूप में प्रेतजस के साथ मामला है।

  • जावास्क्रिप्ट द्वारा उत्सर्जित घटना .click() में क्लिक के निर्देशांक नहीं हैं

    गुणों के clientX, clientY, screenX, screenY, layerX, layerYलिए निर्धारित हैं 0। पृष्ठ उन पर भरोसा कर सकता है और अलग तरह से व्यवहार कर सकता है।


.click()कुछ डेटा को स्क्रैप करने के लिए जावास्क्रिप्ट का उपयोग करना ठीक हो सकता है , लेकिन यह परीक्षण के संदर्भ में नहीं है। यह परीक्षण के उद्देश्य को हरा देता है क्योंकि यह किसी उपयोगकर्ता के व्यवहार का अनुकरण नहीं करता है। इसलिए, यदि ड्राइवर से क्लिक विफल हो जाता है, तो एक वास्तविक उपयोगकर्ता अधिकांश परिस्थितियों में भी एक ही क्लिक करने में विफल हो जाएगा।


जब हम सफल होने की उम्मीद करते हैं, तो ड्राइवर किसी तत्व को क्लिक करने में विफल क्यों हो जाता है?

  • विलंबित या संक्रमण प्रभाव के कारण लक्षित तत्व अभी तक दिखाई नहीं दे रहा है।

    कुछ उदाहरण :

    https://developer.mozilla.org/fr/docs/Web (ड्रॉपडाउन नेविगेशन मेनू) http://materializecss.com/side-nav.html (ड्रॉपडाउन साइड बार)

    Workarrounds:

    दृश्यता, न्यूनतम आकार या स्थिर स्थिति की प्रतीक्षा करने के लिए एक वेटर जोड़ें:

    // wait visible
    browser.wait(ExpectedConditions.visibilityOf(elem), 5000);
    
    // wait visible and not disabled
    browser.wait(ExpectedConditions.elementToBeClickable(elem), 5000);
    
    // wait for minimum width
    browser.wait(function minimumWidth() {
        return elem.getSize().then(size => size.width > 50);
    }, 5000);

    सफल होने तक क्लिक करने का प्रयास करें:

    browser.wait(function clickSuccessful() {
        return elem.click().then(() => true, (ex) => false);
    }, 5000);

    एनीमेशन / संक्रमण की अवधि के मिलान में देरी जोड़ें:

    browser.sleep(250);


  • दृश्य में स्क्रॉल किए जाने पर एक फ़्लोटिंग तत्व द्वारा कवर किया गया लक्षित तत्व समाप्त होता है :

    ड्राइवर स्वचालित रूप से तत्व को दृश्यमान बनाने के लिए स्क्रॉल करता है। यदि पृष्ठ में एक फ़्लोटिंग / चिपचिपा तत्व (मेनू, विज्ञापन, पाद लेख, सूचना, कुकी नीति ..) है, तो तत्व अंत तक कवर हो सकता है और अब दृश्यमान / इंटरेक्टेबल नहीं होगा।

    उदाहरण: https://twitter.com/?lang=en

    समाधान:

    स्क्रॉलिंग या फ़्लोटिंग तत्व से बचने के लिए विंडो का आकार किसी बड़े पर सेट करें।

    एक नकारात्मक Yऑफसेट के साथ तत्व पर होवर करें और फिर इसे क्लिक करें:

      browser.actions()
         .mouseMove(elem, {x: 0, y: -250})
         .click()
         .perform();

    क्लिक करने से पहले तत्व को विंडो के केंद्र में स्क्रॉल करें:

    browser.executeScript(function scrollCenter(elem) {
      var win = elem.ownerDocument.defaultView || window,
        box = elem.getBoundingClientRect(),
        dy = box.top - (win.innerHeight - box.height) / 2;
      win.scrollTo(win.pageXOffset, win.pageYOffset + dy);
    }, element);
    
    element.click();

    यदि इसे टाला नहीं जा सकता है तो चल तत्व को छिपाएं:

    browser.executeScript(function scrollCenter(elem) {
      elem.style.display = 'none';
    }, element);

17

नोट: चलो 'क्लिक' कॉल एंड-यूज़र क्लिक है। 'js click' जेएस के माध्यम से क्लिक होता है

जब एक नियमित वेबड्राइवर क्लिक नहीं करता है तो "जावास्क्रिप्ट के माध्यम से" काम क्यों करता है?

ऐसा होने के लिए 2 मामले हैं:

I. यदि आप PhamtomJS का उपयोग कर रहे हैं

तब यह सबसे आम ज्ञात व्यवहार है PhantomJS। कुछ तत्व कभी-कभी क्लिक करने योग्य नहीं होते हैं, उदाहरण के लिए <div>। ऐसा इसलिए है क्योंकि यह PhantomJSब्राउज़र के इंजन (जैसे प्रारंभिक HTML + CSS -> कंप्यूटिंग सीएसएस -> रेंडरिंग) के अनुकरण के लिए मूल बनाया गया था। लेकिन इसका अंत उपयोगकर्ता के तरीके (देखने, क्लिक करने, खींचने) के रूप में बातचीत करने का नहीं है। इसलिए PhamtomJSकेवल एंड-यूज़र इंटरैक्शन के साथ आंशिक रूप से समर्थित है।

क्यों जेएस क्लिक करें काम करता है? या तो क्लिक के लिए, वे सभी मतलब क्लिक हैं। यह 1 बैरल और 2 ट्रिगर वाली बंदूक की तरह है । व्यूपोर्ट से एक, जेएस से एक। चूंकि PhamtomJSब्राउज़र के इंजन के अनुकरण में महान, एक जेएस क्लिक को पूरी तरह से काम करना चाहिए।

द्वितीय। "क्लिक" के इवेंट हैंडलर को समय की बुरी अवधि में बांधना पड़ा।

उदाहरण के लिए, हमें ए <div>

  • -> हम कुछ गणना करते हैं

  • -> तो हम क्लिक करने की घटना को बांधते हैं <div>

  • -> कोणीय के कुछ खराब कोडिंग के साथ प्लस (जैसे कि गुंजाइश के चक्र को ठीक से नहीं संभालना)

हम उसी परिणाम के साथ समाप्त हो सकते हैं। क्लिक करने से काम नहीं चलेगा, क्योंकि WebdriverJS उस तत्व पर क्लिक करने की कोशिश कर रहा है, जब उसके पास क्लिक हैंडलर नहीं है।

क्यों जेएस क्लिक करें काम करता है? Js क्लिक ब्राउज़र में सीधे js इंजेक्ट करने जैसा है। 2 तरीकों से संभव है,

मुट्ठी devtools कंसोल के माध्यम से है (हाँ, WebdriverJS devtools 'कंसोल के साथ संवाद करता है)।

दूसरा एक <script>टैग को सीधे HTML में इंजेक्ट किया जाता है।

प्रत्येक ब्राउज़र के लिए, व्यवहार भिन्न होगा। लेकिन परवाह किए बिना, बटन पर क्लिक करने की तुलना में ये तरीके अधिक जटिल हैं। क्लिक का उपयोग पहले से ही है (अंत-उपयोगकर्ता क्लिक), js क्लिक पिछले दरवाजे से गुजर रहा है।

और js क्लिक के लिए एक अतुल्यकालिक कार्य दिखाई देगा। यह ' ब्राउज़र एसिंक्रोनस टास्क और सीपीयू टास्क शेड्यूलिंग ' के एक थोड़े जटिल विषय से संबंधित है (इसे कुछ समय पहले पढ़ें फिर से लेख नहीं मिल सकता है)। संक्षेप में यह ज्यादातर परिणाम देगा क्योंकि js क्लिक के लिए CPU के कार्य शेड्यूलिंग के एक चक्र की प्रतीक्षा करनी होगी और यह क्लिक इवेंट के बंधन के बाद थोड़ा धीमा हो जाएगा। (आप इस मामले को तब जान सकते हैं जब आपको तत्व कभी-कभी क्लिक करने योग्य लगे, कभी-कभी नहीं।)

जब वास्तव में ऐसा हो रहा है और इस वर्कअराउंड (यदि कोई हो) के नकारात्मक पक्ष क्या है?

=> जैसा कि ऊपर उल्लेख किया गया है, दोनों का अर्थ एक ही उद्देश्य के लिए है, लेकिन किस प्रवेश द्वार का उपयोग करने के बारे में:

  • क्लिक करें: ब्राउज़र के डिफ़ॉल्ट रूप से जो प्रदान कर रहा है उसका उपयोग कर रहा है।
  • जेएस क्लिक: पिछले दरवाजे से गुजर रहा है।

=> प्रदर्शन के लिए, यह कहना मुश्किल है क्योंकि यह ब्राउज़रों पर निर्भर करता है। लेकिन आम तौर पर:

  • क्लिक: का अर्थ तेज़ नहीं है, बल्कि केवल सीपीयू निष्पादन कार्य की अनुसूची सूची में उच्च स्थान पर हस्ताक्षर किए हैं।
  • जेएस क्लिक: का मतलब धीमी नहीं है, लेकिन केवल यह सीपीयू कार्य की अनुसूची सूची की अंतिम स्थिति में हस्ताक्षरित है।

=> डाउनसाइड्स:

  • क्लिक करें: लगता है कि PhamtomJS का उपयोग करने के अलावा आपको कोई नकारात्मक पहलू नहीं है।
  • जेएस क्लिक: स्वास्थ्य के लिए बहुत बुरा। आप गलती से किसी ऐसी चीज़ पर क्लिक कर सकते हैं जो वहाँ पर नहीं है। जब आप इसका उपयोग करते हैं, तो सुनिश्चित करें कि तत्व वहाँ है और देखने के लिए उपलब्ध है और अंत-उपयोगकर्ता के दृष्टिकोण के रूप में क्लिक करें।

पुनश्च यदि आप एक समाधान की तलाश कर रहे हैं।

  • PhantomJS का उपयोग करना? मैं इसके बजाय क्रोम हेडलेस का उपयोग करने का सुझाव दूंगा। हां, आप उबंटू पर क्रोम हेडलेस सेट कर सकते हैं। थिंग क्रोम की तरह ही चलता है लेकिन इसमें केवल फैंटम जेएस जैसा दृश्य और कम बगिया नहीं है।
  • PhamtomJS का उपयोग नहीं, लेकिन अभी भी समस्या है? मैं browser.wait()( अधिक जानकारी के लिए इस की जाँच करें ) के साथ ExpectedCondition of Protractor का उपयोग करने का सुझाव दूंगा

(मैं इसे छोटा करना चाहता हूं, लेकिन बुरी तरह समाप्त हो गया। सिद्धांत से जुड़ी कोई भी बात समझाने के लिए जटिल है ...)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.