0

In selenium JavaScript, I have to refresh the page until element is disappeared. Since it uses promises, if I use for loop it will create many promise even if the condition is satisfied, later it will be resolved. Also I have to provide driver.sleep(5000) mandatory due to some reason.

$browser.get("https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html").
then( function()
{
var p=Promise.resolve();
for (let index = 0; index < 5; index++) {    
    p = p.then(() => 
    isElementDisplayedAfterrefresh($driver.By.xpath("//span[text()='PouchDB']"), "input"))
    .then(a=>$browser.sleep(3000))
    .then(()=>$browser.navigate().refresh())
}
return p;
}
).then(
    ()=>console.log('done'))

code should exit if element is not displayed, it should refresh if element is still displayed. How to loop through promise sequentially when we don't know results/number of iterations the return type is Promise, How to break loop? thanks

Edit

https://gist.github.com/saiparth/045c32267e55b836f139bdac6597e57b Issue is it schedules commands for loop, so all 5 iteration will execute no matter for previous index worked not. Also I should not use async/await

SSP
  • 85
  • 7
  • What does `isElementDisplayedAfterrefresh()` look like? Also, is it intentional you aren't using `index` in the loop? – C. Peck May 30 '21 at 17:50
  • @C.Peck function `isElementDisplayedAfterrefresh(by, helpingText) { console.log("Refreshing the page for element to disappear '" + helpingText + "' [locator " + by + " ]"); return $browser.findElements(by) .then(a =>a.length) .then(a=>a==0); }` – SSP May 31 '21 at 02:20

2 Answers2

1

How do you know if the element is displayed or not, seems like you are refreshing the page anyway if I am reading it correctly? .then(a=>$browser.sleep(3000)) shouldn't it be something like

.then((a => { if(a.isDisplayed() == true) { console.log('element displayed dont do anything') } 
  else { 
     $browser.sleep(3000))
    .then(()=>$browser.navigate().refresh())
}  }))
C. Peck
  • 3,641
  • 3
  • 19
  • 36
Dhiraj
  • 2,687
  • 2
  • 10
  • 34
  • Instead of `a.display` I think you mean `a.isDisplayed()`? Also I think the condition should check if `a.isDisplayed() == false` – C. Peck May 30 '21 at 18:42
  • I am not sure about the exact params but just to make sure to check for condition before taking action – Dhiraj May 30 '21 at 18:44
  • 1
    `isDisplayed()` is the right syntax for checking this with the built-in selenium function, I made that edit if that's OK. – C. Peck May 30 '21 at 18:45
  • @Dhiraj Issue is not with that, issue is when for loop runs it schedules all commands. so eve though element disapeared, still there will be pending commands in que and they will execute later. Please run this https://gist.github.com/saiparth/045c32267e55b836f139bdac6597e57b – SSP May 31 '21 at 02:45
  • can you try something like `return Promise.reject('element displayed dont do anything');` If promise chaining becomes cumbersome and non-readable you can always use async/await `await $browser.get("https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html").` – Dhiraj May 31 '21 at 05:56
  • unfortunately I cant use async/await in the app. and problem is even if you reject, the for loop will schedule so many commands, break for loop will not work with promises. – SSP May 31 '21 at 06:25
0

Finally I found the solution after referring this

function process(index) {
    if (index >= 10) {
        return;
    }
   return $browser.findElements(By.xpath("//span[text()='PouchDB']")).then(a => a.length==0)
        .then(function (isDisplayed) 
        {
            if (!isDisplayed) {
               return $browser.sleep(5000)
                .then(() => $browser.navigate().refresh())
                .then(a=>process(index + 1))
            }  
            else{
               return;
            }
        });
}
$browser.manage().window().maximize();
$browser.get("https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html")
.then(a=>process(5))
.then(a=>console.log('done'))
SSP
  • 85
  • 7