木偶-测试不执行任何操作

时间:2019-05-28 20:19:46

标签: javascript testing browser automated-tests puppeteer

所以,我在和Jest一起使用Puppeteer。添加后

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

我的测试未执行任何操作。我使用无头模式还是将其称为“正常”模式都没有关系。有人可以帮助我吗?

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

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);
  }
};

1 个答案:

答案 0 :(得分:0)

答案分为两部分,一部分为普通jest,另一部分为jest-puppeteer。如果需要,您可以跳至jest-puppeteer

问题(jest):

browser块内的pagebeforeAllit块无关。它也与page类中的HomePage没有任何关系。

您没有提及您是否在使用jest-puppeteer

解决方案:

为describe块创建块范围的变量,并将页面对象传递给模块。

定义HomePage类

请考虑以下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();
  }
}

如您所见,有两种方法可以访问类中的页面。可以在构造函数内部传递,也可以直接与方法一起使用。

方法getScreenshot有一个this.page,而方法getTitle可以访问一个page

完善测试

由于this issue,无法在玩笑测试中使用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;
  });
});

现在,所有其他块都可以访问该页面。根据前面的示例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
});

最后我们清理测试,

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

我们可能需要使用detectOpenHandles来进行headfull模式的开玩笑的测试。

jest . --detectOpenHandles

结果:

问题(jest-puppeteer):

jest-puppeteer已经为您提供了一个全局浏览器和页面对象。您无需定义任何内容。

但是,如果要使用jest-puppeteerexpect-puppeteer,则必须使用自定义配置文件。

解决方案:

创建一个jest-config.json文件并放入内容,

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

现在,摆脱浏览器和页面创建代码以及afterAll的所有page.close钩子。

这是一个有效的测试文件,

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");
  });
});

让我们运行它,

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

结果: