Puppeteer - 测试不执行任何操作
Puppeteer - the tests do not perform any action
因此,我将 Puppeteer 与 Jest 结合使用。添加后
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
我的测试没有执行任何操作。无论我使用的是无头模式还是我们称之为 "normal" 模式都没有关系。有人可以帮帮我吗?
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);
}
};
答案有两部分,一部分是正常的jest
,另一部分是jest-puppeteer
。如果需要,您可以跳到 jest-puppeteer
。
问题(jest
):
beforeAll
块中的 browser
和 page
与 it
块无关。它也与HomePage
class中的page
没有任何关系。
你没有提到你是否使用 jest-puppeteer
。
解决方案:
为描述块创建块范围变量,并将页面对象传递给模块。
优化主页class
考虑以下 HomePage
class.
// HomePage.js
class HomePage {
constructor(page) {
this.page = page;
}
async getScreenshot() {
await this.page.screenshot({ path: "example.png" });
}
async getTitle(page) {
return page.title();
}
}
如您所见,有两种方法可以访问class内的页面。要么在构造函数内部传递,要么直接与方法一起使用。
方法 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 class,我们可以根据我们如何定义方法来执行以下任一操作。
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-puppeteer
和 expect-puppeteer
,则必须使用自定义配置文件。
解决方案:
创建一个jest-config.json
文件并放入内容,
{
"preset": "jest-puppeteer",
"setupFilesAfterEnv": ["expect-puppeteer"]
}
现在,摆脱浏览器和页面创建代码,以及 page.close
的任何 afterAll
挂钩。
这是一个有效的测试文件,
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
结果:
因此,我将 Puppeteer 与 Jest 结合使用。添加后
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
我的测试没有执行任何操作。无论我使用的是无头模式还是我们称之为 "normal" 模式都没有关系。有人可以帮帮我吗?
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);
}
};
答案有两部分,一部分是正常的jest
,另一部分是jest-puppeteer
。如果需要,您可以跳到 jest-puppeteer
。
问题(jest
):
beforeAll
块中的 browser
和 page
与 it
块无关。它也与HomePage
class中的page
没有任何关系。
你没有提到你是否使用 jest-puppeteer
。
解决方案:
为描述块创建块范围变量,并将页面对象传递给模块。
优化主页class
考虑以下 HomePage
class.
// HomePage.js
class HomePage {
constructor(page) {
this.page = page;
}
async getScreenshot() {
await this.page.screenshot({ path: "example.png" });
}
async getTitle(page) {
return page.title();
}
}
如您所见,有两种方法可以访问class内的页面。要么在构造函数内部传递,要么直接与方法一起使用。
方法 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 class,我们可以根据我们如何定义方法来执行以下任一操作。
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-puppeteer
和 expect-puppeteer
,则必须使用自定义配置文件。
解决方案:
创建一个jest-config.json
文件并放入内容,
{
"preset": "jest-puppeteer",
"setupFilesAfterEnv": ["expect-puppeteer"]
}
现在,摆脱浏览器和页面创建代码,以及 page.close
的任何 afterAll
挂钩。
这是一个有效的测试文件,
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