java في - سيلديري WebDriver: انتظر صفحة معقدة مع جافا سكريبت (JS) لتحميل




7 Answers

إذا كان أي شخص يعرف بالفعل جوابًا عامًا دائمًا ، فسيكون قد تم تنفيذه في كل مكان منذ العصور وسيجعل حياتنا أسهل بكثير.

هناك العديد من الأشياء التي يمكنك القيام بها ، ولكن كل واحد منهم لديه مشكلة:

  1. كما قال اشوين برابهو ، إذا كنت تعرف السيناريو جيدا ، يمكنك مراقبة سلوكه وتتبع بعض المتغيرات على window أو document الخ. هذا الحل ، ومع ذلك ، ليس للجميع ويمكن استخدامه فقط من قبلك وفقط على أساس محدود مجموعة من الصفحات.

  2. الحل الخاص بك عن طريق ملاحظة رمز HTML وما إذا كان قد تغير أو لم يتم تغييره لبعض الوقت ليس سيئًا (أيضًا ، هناك طريقة للحصول على HTML الأصلي وغير المحرر مباشرة من WebDriver ) ، ولكن:

    • يستغرق الأمر وقتًا طويلاً لتأكيد صفحة ما وقد يؤدي إلى إطالة الاختبار بشكل كبير.
    • أنت لا تعرف أبدا ما هو الفاصل الزمني الصحيح. قد يكون البرنامج النصي تنزيل شيء كبير يستغرق أكثر من 500 مللي ثانية. هناك العديد من البرامج النصية على الصفحة الداخلية لشركتنا والتي تستغرق عدة ثوانٍ في IE. قد يكون جهاز الكمبيوتر الخاص بك قصيرًا مؤقتًا على الموارد - لنفترض أن أحد برامج مكافحة الفيروسات سيجعل وحدة المعالجة المركزية تعمل بشكل كامل ، ثم قد يكون 500 مللي ثانية قصيرًا جدًا حتى بالنسبة للنصوص غير المعقدة.
    • بعض النصوص لا يتم أبدا. يسمون أنفسهم مع بعض التأخير ( setTimeout() ) والعمل مرارا وتكرارا ، وربما يمكن تغيير HTML في كل مرة يتم تشغيلها. على محمل الجد ، كل صفحة "ويب 2.0" يفعل ذلك. حتى Stack Overflow. يمكنك كتابة أكثر الطرق شيوعًا المستخدمة والنظر في النصوص البرمجية التي تستخدمها على أنها مكتملة ، ولكن ... لا يمكنك التأكد من ذلك.
    • ماذا لو كان البرنامج النصي يقوم بشيء آخر غير تغيير HTML؟ يمكن أن يفعل الآلاف من الأشياء ، وليس فقط بعض المتعة الداخلية innerHTML .
  3. هناك أدوات لمساعدتك في ذلك. nsIWebProgressListener التقدم جنبا إلى جنب مع nsIWebProgressListener وبعض الآخرين. دعم المتصفح لهذا ، ومع ذلك ، فظيع. بدأ فايرفوكس في محاولة لدعمه من FF4 فصاعدا (لا يزال يتطور) ، IE لديه دعم أساسي في IE9.

وأظن أنه يمكنني التوصل إلى حل معيب آخر قريبًا. والحقيقة هي - لا توجد إجابة محددة عن وقت القول "الآن تكتمل الصفحة" بسبب النصوص الأبديّة التي تؤدي عملها. اختر الشخص الذي يخدمك بشكل أفضل ، ولكن احذر من أوجه القصور فيه.

المتصفح شرح

لدي تطبيق على شبكة الإنترنت لاختبار مع السيلينيوم. هناك الكثير من جافا سكريبت قيد التشغيل عند تحميل الصفحة.
شفرة جافا سكريبت ليست مكتوبة بشكل جيد ولكن لا يمكنني تغيير أي شيء. لذا فإن انتظار ظهور عنصر ما في DOM باستخدام طريقة findElement() ليس خيارًا.
أريد إنشاء وظيفة عامة في جافا للانتظار حتى يتم تحميل صفحة ، يكون الحل المحتمل:

  • قم بتشغيل نموذج سكريبت JavaScript WebDriver وتخزين نتيجة document.body.innerHTML في نص متغير السلسلة.
  • مقارنة متغير body مع الإصدار السابق من body . إذا كانت هي نفسها ثم قم بتعيين زيادة عداد notChangedCount غير ذلك تعيين notChangedCount إلى صفر.
  • انتظر وقت litte (50 مللي ثانية على سبيل المثال).
  • إذا لم تتغير الصفحة لبعض الوقت (500 مللي ثانية على سبيل المثال) لذلك notChangedCount > = 10 ثم الخروج من حلقة أخرى حلقة إلى الخطوة الأولى.

هل تعتقد أنه حل صحيح؟




يجب الانتظار حتى انتهاء تحميل جافا سكريبت و jQuery. قم jQuery.active جافا سكريبت للتحقق مما اذا كان jQuery.active هو 0 و document.readyState complete ، مما يعني اكتمال تحميل JS و jQuery.

public boolean waitForJStoLoad() {

    WebDriverWait wait = new WebDriverWait(driver, 30);

    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          return ((Long)executeJavaScript("return jQuery.active") == 0);
        }
        catch (Exception e) {
          return true;
        }
      }
    };

    // wait for Javascript to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return executeJavaScript("return document.readyState")
            .toString().equals("complete");
      }
    };

  return wait.until(jQueryLoad) && wait.until(jsLoad);
}



يعمل الرمز أدناه بشكل مثالي في حالتي - تحتوي صفحتي على برامج Java معقدة

public void checkPageIsReady() {

  JavascriptExecutor js = (JavascriptExecutor)driver;


  //Initially bellow given if condition will check ready state of page.
  if (js.executeScript("return document.readyState").toString().equals("complete")){ 
   System.out.println("Page Is loaded.");
   return; 
  } 

  //This loop will rotate for 25 times to check If page Is ready after every 1 second.
  //You can replace your value with 25 If you wants to Increase or decrease wait time.
  for (int i=0; i<25; i++){ 
   try {
    Thread.sleep(1000);
    }catch (InterruptedException e) {} 
   //To check page ready state.
   if (js.executeScript("return document.readyState").toString().equals("complete")){ 
    break; 
   }   
  }
 }

المصدر - كيفية الانتظار لصفحة لتحميل / جاهز في سيلديوم WebDriver




إذا كان كل ما عليك القيام به هو الانتظار حتى تصبح html على الصفحة مستقرة قبل محاولة التفاعل مع العناصر ، يمكنك استطلاع DOM بشكل دوري ومقارنة النتائج ، إذا كانت DOM هي نفسها خلال وقت الاستطلاع المحدد ، الذهبي. شيء من هذا القبيل حيث تمر في الحد الأقصى لوقت الانتظار والوقت بين استطلاعات الرأي صفحة قبل مقارنة. بسيطة وفعالة.

public void waitForJavascript(int maxWaitMillis, int pollDelimiter) {
    double startTime = System.currentTimeMillis();
    while (System.currentTimeMillis() < startTime + maxWaitMillis) {
        String prevState = webDriver.getPageSource();
        Thread.sleep(pollDelimiter); // <-- would need to wrap in a try catch
        if (prevState.equals(webDriver.getPageSource())) {
            return;
        }
    }
}



يمكنك كتابة بعض المنطق للتعامل مع هذا. لدي كتابة أسلوب سيعود إلى WebElement وسيتم استدعاء هذه الطريقة ثلاث مرات أو يمكنك زيادة الوقت وإضافة فحص فارغ لـ WebElement هنا مثال

public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.get("https://www.crowdanalytix.com/#home");
        WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
        int i = 1;
        while (webElement == null && i < 4) {
            webElement = getWebElement(driver, "homessssssssssss");
            System.out.println("calling");
            i++;
        }
        System.out.println(webElement.getTagName());
        System.out.println("End");
        driver.close();
    }

    public static WebElement getWebElement(WebDriver driver, String id) {
        WebElement myDynamicElement = null;
        try {
            myDynamicElement = (new WebDriverWait(driver, 10))
                    .until(ExpectedConditions.presenceOfElementLocated(By
                            .id(id)));
            return myDynamicElement;
        } catch (TimeoutException ex) {
            return null;
        }
    }



يمكن استخدام شرطين للتحقق من تحميل الصفحة قبل البحث عن أي عنصر في الصفحة:

WebDriverWait wait = new WebDriverWait(driver, 50);

باستخدام أدناه سوف تنتظر redayState حتى تحميل الصفحة

wait.until((ExpectedCondition<Boolean>) wd ->
   ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));

أدناه ، سينتظر JQuery حتى لا يتم تحميل البيانات

  int count =0;
            if((Boolean) executor.executeScript("return window.jQuery != undefined")){
                while(!(Boolean) executor.executeScript("return jQuery.active == 0")){
                    Thread.sleep(4000);
                    if(count>4)
                        break;
                    count++;
                }
            }

بعد هذه JavaScriptCode في محاولة للعثور على webElement.

WebElement we = wait.until(ExpectedConditions.presenceOfElementLocated(by));



طلبت من مطوّري البرامج إنشاء متغير جافا سكريبت "isProcessing" الذي يمكنني الوصول إليه (في كائن "ae") الذي قاموا بتعيينه عند بدء تشغيل الأشياء ومسحها عند حدوث الأشياء. ثم أقوم بتشغيله في جهاز تخزين يتحقق منه كل 100 مللي ثانية حتى يحصل على خمس صفات بحد أقصى 500 مللي ثانية بدون أي تغييرات. إذا مرت 30 ثانية ، فأنا أرمي استثناءًا لأنه كان يجب أن يحدث شيء ما في ذلك الوقت. هذا في C #.

public static void WaitForDocumentReady(this IWebDriver driver)
{
    Console.WriteLine("Waiting for five instances of document.readyState returning 'complete' at 100ms intervals.");
    IJavaScriptExecutor jse = (IJavaScriptExecutor)driver;
    int i = 0; // Count of (document.readyState === complete) && (ae.isProcessing === false)
    int j = 0; // Count of iterations in the while() loop.
    int k = 0; // Count of times i was reset to 0.
    bool readyState = false;
    while (i < 5)
    {
        System.Threading.Thread.Sleep(100);
        readyState = (bool)jse.ExecuteScript("return ((document.readyState === 'complete') && (ae.isProcessing === false))");
        if (readyState) { i++; }
        else
        {
            i = 0;
            k++;
        }
        j++;
        if (j > 300) { throw new TimeoutException("Timeout waiting for document.readyState to be complete."); }
    }
    j *= 100;
    Console.WriteLine("Waited " + j.ToString() + " milliseconds. There were " + k + " resets.");
}



Related

java selenium webdriver selenium-webdriver