skip to Main Content

Locator page.locator(‘.inner-blocks div.img-block’) returns 3 images. I want to verify one by one that all three images are visible on the Page. I am using Page Object Pattern. My page Object class looks like this

Dashboard.js

class dashboardPage{
constructor(page)
{
this.ImageBlocks = page.locator('.inner-blocks div.img-block')
 }
async verifytopSectionThreeBlocks()
{
const totalblocks = await this.ImageBlocks.count()
console.log("total count:"+totalblocks)
for(let i=0;i<totalblocks;i++)
{
   
     return (await this.ImageBlocks.nth(i))
}
}
}
module.exports ={dashboardPage};

And in the test class i am trying to assert that all images are visible.

const result = dashboardpage.verifytopSectionThreeBlocks()
 await except (result).toBeVisible()

This is giving error. Could anyone point it out and fix what is wrong here.

2

Answers


  1. You wrote the loop with a return statement; however, functions can only return one value. This means that your loop will perform only one iteration and stop afterward because the function’s execution will conclude. As a result, you will always receive only the first image.

    Try running this code to confirm:

    function test() {
      for(let i = 0; i < 5; i++) {
        return i
      }
    }
    
    console.log(test())

    To check all images, you can modify the code to return an array of images. Then, within the test, you can iterate through the array to perform the necessary checks.

    const imageBlocks = await page.locator('.inner-blocks div.img-block');
    
    for(let image of imageBlock) {
      await expect(image).toBeVisible()
    }
    
    Login or Signup to reply.
  2. This answer has the right idea, but is missing .all():

    import {expect, test} from "@playwright/test"; // ^1.39.0
    
    // sample page to prove example correctness
    const html = `<!DOCTYPE html>
    <html>
    <body>
    <div class="inner-blocks">
      <div class="img-block"></div>
      <div class="img-block"></div>
      <div class="img-block"></div>
    </div>
    <script>
    
    // make the elements visible after 2 seconds
    setTimeout(() => {
      document.querySelectorAll(".img-block").forEach(e => {
        e.textContent = "added";
      });
    }, 2000);
    </script>
    </body>
    </html>`;
    
    test("all image blocks are eventually visible", async ({page}) => {
      await page.setContent(html);
      const imageBlocks = page.locator(".inner-blocks div.img-block");
      await expect(imageBlocks).toHaveCount(3);
    
      for (const imageBlock of await imageBlocks.all()) {
        await expect(imageBlock).toBeVisible();
      }
    });
    

    In a POM:

    // ... same sample HTML and imports
    
    class DashboardPage {
      constructor(page) {
        this.page = page;
        this.imageBlocks = page.locator(".inner-blocks div.img-block");
      }
    
      goto() {
        return this.page.setContent(html); // for testing; replace with goto
      }
    
      get topSectionBlocks() {
        return this.imageBlocks;
      }
    }
    
    // ...
    
    test("3 image blocks are eventually visible", async ({page}) => {
      const dashboard = new DashboardPage(page);
      await dashboard.goto();
      await expect(dashboard.topSectionBlocks).toHaveCount(3);
    
      for (const block of await dashboard.topSectionBlocks.all()) {
        await expect(block).toBeVisible();
      }
    });
    

    A few notes:

    • return ends the function, breaking the loop at the first iteration.
    • Avoid count()/nth().
    • except should be expect.
    • Always format code so it’s readable.
    • Class names should always be UpperPascalCase, not camelCase. Similarly, this.ImageBlocks should be camelCase instead of UpperPascalCase, so this.imageBlocks.
    • verifytopSectionThreeBlocks doesn’t actually verify anything, just retrieves locators. I’d call it topSectionBlocks or similar.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search