如何用 puppeteer 和 jest 编写健壮的测试?
How to write robust test with puppeteer and jest?
这是我写的测试,我的问题是,我试图尽可能健壮地构建它,但它有时会工作,有时会失败,原因如下所示。
也许我遗漏了一些东西,如果你们中的任何一个能帮助我使测试更健壮,我将不胜感激。
注意:我从代码中删除了敏感信息。
const { getStatement, portalLogin, getDeletableList } = require("./helper.js");
const user = { userName: "*****@*****.de", passWord: "*******" };
const puppeteer = require("puppeteer");
const headlessVal = false;
const webSiteUrlLogin = "https://... .de/dashboard";
const webSiteUrlMe = "https://... .de/me";
// elements with classes
const change_username_button = ".change-username-button";
const save_user_changes_btn = ".save-user-changes-btn";
// elements with ID's
const user_personal_title = "#user_personal_title";
// [happy path] 1 user changes #user_personal_title
test("[happy path] 1 user changes #user_personal_title", async () => {
//////// SETUP & LOGIN START /////////
const browser = await puppeteer.launch({
headless: headlessVal,
args: ["--window-size=1920,1080"],
defaultViewport: null,
});
// new browser window opens
const page = await browser.newPage();
// open specified url and waits for it to be loaded
await page.goto(webSiteUrlLogin, {
//wait until there are no more conections that traffic
waitUntil: "networkidle0",
});
await page.waitForNavigation({
waitUntil: "networkidle2",
});
const user_local = {
userName:
user.userName !== undefined ? user.userName : process.env.USERNAME,
passWord:
user.passWord !== undefined ? user.passWord : process.env.PASSWORD,
};
await page.waitForTimeout(500);
await page.evaluate((user_local) => {
<FUNCTION LOGIN>
}, user_local);
await page.waitForTimeout(600);
//////// SETUP & LOGIN DONE /////////
//////// TEST START /////////
getStatement({ msg: "[START]: 1.1 title: '' >'Prof'.", runlocally: true });
await page.waitForTimeout(650);
await page.goto(webSiteUrlMe, {
waitUntil: "networkidle0",
});
// 1 change #user_personal_title from '' >> 'Prof.'
console.log("1 change #user_personal_title from '' >> 'Prof.'");
await page.waitForTimeout(650);
await page.evaluate((user_personal_title) => {
document.querySelector(user_personal_title).value = "";
}, user_personal_title);
await page.type(user_personal_title, "Prof.");
let user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.waitForTimeout(650);
await page.evaluate(() => {
document.querySelector("#user_personal_title").value = "";
});
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("");
////// TEST DONE //////////
await page.click(".sign-out");
await page.removeAllListeners();
await page.close();
await browser.close();
getStatement({ msg: "[ENDING]: 1.1 ", runlocally: true });
}, 12000);
失败:
Evaluation failed: TypeError: Cannot set property 'value' of null
at __puppeteer_evaluation_script__:2:55
at ExecutionContext._evaluateInternal (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:217:19)
at ExecutionContext.evaluate (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:16)
at Object.<anonymous> (joyce_PORTAL/end-to-end/me.test.js:168:3)
您在 document.querySelector(user_personal_title).value
中选择的元素在页面上尚不可用。在使用 waitForSelector(selector)
.
执行页面之前,您需要等待选择器元素在页面上可用
简单POC如下:
page.waitForSelector(user_personal_title)
.then(() => //evaluate your document.querySelector(user_personal_title).value code here
);
//or simply
await page.waitForSelector(user_personal_title)
这是我写的测试,我的问题是,我试图尽可能健壮地构建它,但它有时会工作,有时会失败,原因如下所示。 也许我遗漏了一些东西,如果你们中的任何一个能帮助我使测试更健壮,我将不胜感激。
注意:我从代码中删除了敏感信息。
const { getStatement, portalLogin, getDeletableList } = require("./helper.js");
const user = { userName: "*****@*****.de", passWord: "*******" };
const puppeteer = require("puppeteer");
const headlessVal = false;
const webSiteUrlLogin = "https://... .de/dashboard";
const webSiteUrlMe = "https://... .de/me";
// elements with classes
const change_username_button = ".change-username-button";
const save_user_changes_btn = ".save-user-changes-btn";
// elements with ID's
const user_personal_title = "#user_personal_title";
// [happy path] 1 user changes #user_personal_title
test("[happy path] 1 user changes #user_personal_title", async () => {
//////// SETUP & LOGIN START /////////
const browser = await puppeteer.launch({
headless: headlessVal,
args: ["--window-size=1920,1080"],
defaultViewport: null,
});
// new browser window opens
const page = await browser.newPage();
// open specified url and waits for it to be loaded
await page.goto(webSiteUrlLogin, {
//wait until there are no more conections that traffic
waitUntil: "networkidle0",
});
await page.waitForNavigation({
waitUntil: "networkidle2",
});
const user_local = {
userName:
user.userName !== undefined ? user.userName : process.env.USERNAME,
passWord:
user.passWord !== undefined ? user.passWord : process.env.PASSWORD,
};
await page.waitForTimeout(500);
await page.evaluate((user_local) => {
<FUNCTION LOGIN>
}, user_local);
await page.waitForTimeout(600);
//////// SETUP & LOGIN DONE /////////
//////// TEST START /////////
getStatement({ msg: "[START]: 1.1 title: '' >'Prof'.", runlocally: true });
await page.waitForTimeout(650);
await page.goto(webSiteUrlMe, {
waitUntil: "networkidle0",
});
// 1 change #user_personal_title from '' >> 'Prof.'
console.log("1 change #user_personal_title from '' >> 'Prof.'");
await page.waitForTimeout(650);
await page.evaluate((user_personal_title) => {
document.querySelector(user_personal_title).value = "";
}, user_personal_title);
await page.type(user_personal_title, "Prof.");
let user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("Prof.");
await page.waitForTimeout(650);
await page.evaluate(() => {
document.querySelector("#user_personal_title").value = "";
});
await page.click(save_user_changes_btn);
await page.waitForNavigation({
//wait until there are no more conections that have traffic
waitUntil: "networkidle0",
});
user_personal_title_val = await page.$eval(
user_personal_title,
(el) => el.value
);
expect(user_personal_title_val).toBe("");
////// TEST DONE //////////
await page.click(".sign-out");
await page.removeAllListeners();
await page.close();
await browser.close();
getStatement({ msg: "[ENDING]: 1.1 ", runlocally: true });
}, 12000);
失败:
Evaluation failed: TypeError: Cannot set property 'value' of null
at __puppeteer_evaluation_script__:2:55
at ExecutionContext._evaluateInternal (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:217:19)
at ExecutionContext.evaluate (node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:106:16)
at Object.<anonymous> (joyce_PORTAL/end-to-end/me.test.js:168:3)
您在 document.querySelector(user_personal_title).value
中选择的元素在页面上尚不可用。在使用 waitForSelector(selector)
.
执行页面之前,您需要等待选择器元素在页面上可用
简单POC如下:
page.waitForSelector(user_personal_title)
.then(() => //evaluate your document.querySelector(user_personal_title).value code here
);
//or simply
await page.waitForSelector(user_personal_title)