简体   繁体   English

Puppeteer - 测试不执行任何操作

[英]Puppeteer - the tests do not perform any action

so, I'm using Puppeteer with Jest. 所以,我正在使用Puppeteer和Jest。 After adding 添加后

    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();

My tests does not perform any actions. 我的测试不执行任何操作。 It doesn't matter if I'm using headless mode or let's call it "normal" mode. 如果我使用无头模式或者将其称为“正常”模式并不重要。 Anybody can help me? 有人可以帮帮我吗?

homepage.test.js homepage.test.js

const puppeteer = require('puppeteer');
const HomePage = require('./page_objects/HomePage');

const homePage = new HomePage();
describe('Homepage', () => {
  beforeAll(async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.goto(homePage.path);
    await page.waitForSelector(homePage.loginPanel);
  });
  it('Log into your account', async () => {
    await homePage.fillLoginForm();
    await expect(page).toMatchElement(homePage.productList);
    await page.screenshot({ path: 'example.png' });
  });

HomePage.js HomePage.js

module.exports = class HomePage {
  constructor() {
    this.path = 'https://www.saucedemo.com/index.html';
    this.loginPanel = '#login_button_container';
    this.productList = 'div[class="inventory_container"]';
    this.loginForm = {
      fields: {
        usernameInput: 'input[id="user-name"]',
        passwordInput: 'input[id="password"]',
        logInButton: 'input[class="btn_action"]',
      },
    };
  }

  async fillLoginForm() {
    await page.type(this.loginForm.fields.usernameInput, 'standard_user');
    await page.type(this.loginForm.fields.passwordInput, 'secret_sauce');
    await page.click(this.loginForm.fields.logInButton);
  }
};

The answer has two parts, one with normal jest and another with jest-puppeteer . 答案有两部分,一部分是正常的jest ,另一部分是jest-puppeteer You can skip to the jest-puppeteer if you want. 如果你愿意,你可以跳到jest-puppeteer

Problem (with jest ): 问题( jest ):

The browser and page inside beforeAll block has no relation to the it blocks. beforeAll块中的browserpageit块无关。 It also does not have any relation with the page inside HomePage class as well. 它也与HomePage类中的page没有任何关系。

You did not mention if you were using jest-puppeteer or not. 你没有提到你是否使用了jest-puppeteer

Solution: 解:

Create block scoped variables for the describe block, and pass the page object to the modules. 为describe块创建块范围变量,并将页面对象传递给模块。

Refining the HomePage class 精炼HomePage类

Consider the following HomePage class. 考虑以下HomePage类。

// HomePage.js
class HomePage {
  constructor(page) {
    this.page = page;
  }

  async getScreenshot() {
    await this.page.screenshot({ path: "example.png" });
  }

  async getTitle(page) {
    return page.title();
  }
}

As you can see, there are two ways to access to the page inside the class. 如您所见,有两种方法可以访问类中的页面。 Either pass inside the constructor, or use with the method directly. 在构造函数内部传递,或直接与方法一起使用。

The method getScreenshot has a this.page , while getTitle has access to a page . getScreenshot方法有一个this.page ,而getTitle可以访问page

Refining the test 完善测试

You cannot use this inside the jest tests due to this issue , but you can declare a variable on top of a block, then access it later. 由于此问题 ,您无法在jest测试中使用this ,但您可以在块顶部声明变量,然后再访问它。

describe("Example", () => {
  // define them up here inside the parent block
  let browser;
  let page;
  let homepage;

  beforeAll(async () => {
    // it has access to the browser, page and homepage
    browser = await puppeteer.launch({ headless: true });
    page = await browser.newPage();
    homepage = new HomePage(page); // <-- pass the page to HomePage here

    await page.goto("http://example.com");
    await page.waitForSelector("h1");
    return true;
  });
});

Now all other blocks can access to the page. 现在所有其他块都可以访问该页面。 According to our previous example HomePage class, we can do either of following depending on how we defined the methods. 根据我们之前的示例HomePage类,我们可以根据我们如何定义方法来执行以下任一操作。

it("Gets the screenshot", async () => {
    await homepage.getScreenshot(); // <-- will use this.page
  });
it("Gets the title", async () => {
    await homepage.getTitle(page); // <-- will use the page we are passing on
});

Finally we cleanup the tests, 最后我们清理测试,

afterAll(async () => {
    await page.close();
    await browser.close();
    return true;
});

We probably need to run the jest tests with detectOpenHandles for headfull mode. 我们可能需要使用detectOpenHandlesdetectOpenHandles模式运行jest测试。

jest . --detectOpenHandles

Result: 结果:

Problem (with jest-puppeteer ): 问题(与jest-puppeteer ):

jest-puppeteer already gives you a global browser and page object. jest-puppeteer已经为您提供了一个全局浏览器和页面对象。 You do not need define anything. 你不需要定义任何东西。

However if you want to use jest-puppeteer and expect-puppeteer , you have to use a custom config file. 但是,如果您想使用jest-puppeteerexpect-puppeteer ,则必须使用自定义配置文件。

Solution: 解:

Create a jest-config.json file and put the contents, 创建一个jest-config.json文件并放入内容,

{
  "preset": "jest-puppeteer",
  "setupFilesAfterEnv": ["expect-puppeteer"]
}

Now, get rid of browser and page creation code, as well as any afterAll hooks for page.close as well. 现在,摆脱浏览器和网页创建代码,以及任何的afterAll对于挂钩page.close为好。

Here is a working test file, 这是一个工作测试文件,

class HomePage {
  async getTitle() {
    return page.$("h1");
  }
}

describe("Example", () => {
  const homepage = new HomePage();
  beforeAll(async () => {
    // it has access to a global browser, page and scoped homepage

    await page.goto("http://example.com");
    await page.waitForSelector("h1");
  });
  it("Gets the screenshot", async () => {
    const element = await homepage.getTitle();
    await expect(element).toMatch("Example");
  });
});

And let's run this, 让我们运行这个,

jest . --detectOpenHandles --config jest-config.json

Result: 结果:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM