提问人:karalkal 提问时间:10/21/2023 最后编辑:karalkal 更新时间:10/24/2023 访问量:37
傀儡师测试 - CdpElementHandle.click() 似乎不起作用
Puppeteer testing - CdpElementHandle.click() doesn't seem to work
问:
我正试图对 Puppeteer 的工作原理有一些基本的了解,并且正在苦苦挣扎。
我正在测试的应用程序可以在这里找到。
单击登录按钮后,应用程序应重定向到 Spotify 并获得 AOuth 授权以搜索 API 并在登录用户帐户中创建和保存播放列表。
但是,我不认为我的测试会点击该按钮,尽管它“找到”了它 - 它似乎在模式下没有做任何事情,当然也不会重定向到任何地方。当然,测试也失败了。
如果我设法以一种或另一种方式解决这个问题,我是否能够在“测试模式”中获得令牌(对不起,愚蠢的表达,希望它足够清楚)?我无法想象能够做到这一点,因为 Puppeteer 必须“登录”到 Spotify,但必须有办法。
顺便说一句,任何人都可以解释一下表达方式的实际作用。如果我用有意义的东西替换参数,即 10000,我就会收到超时错误。字符串值实际上有什么作用?
谢谢。headless: false
await page.waitForTimeout(HEADING_SELECTOR);
const puppeteer = require('puppeteer');
const { expect } = require('chai');
const _ = require('lodash');
const globalVariables = _.pick(global, ['browser', 'expect']);
// puppeteer options
const opts = {
headless: false,
slowMo: 100,
timeout: 10000
};
// expose variables
before(async function () {
global.expect = expect;
global.browser = await puppeteer.launch(opts);
});
// close browser and reset global variables
after(function () {
browser.close();
global.browser = globalVariables.browser;
global.expect = globalVariables.expect;
});
describe('sample test', function () {
// By default, Mocha tests have a 2 second timeout (which means that the test needs to be completed in 2 seconds).
// You can increase it (in milliseconds) as follows:
this.timeout(8000); // this test can take up to 5 seconds
let page;
before(async function () {
page = await browser.newPage();
await page.goto('http://localhost:3000');
});
after(async function () {
await page.close();
})
// TESTS
it('should work', async function () {
console.log(await browser.version());
expect(true).to.be.true;
});
it('should have the correct page title', async function () {
expect(await page.title()).to.eql('Spotify Playlist Creator');
});
it('should have correct heading', async function () {
const HEADING_SELECTOR = 'h1';
let heading;
page.waitForSelector(HEADING_SELECTOR)
/*
page.$eval takes two arguments - selector and pageFunction.
It runs a document.querySelector in the browser environment and passes the result to the pageFunction.
Finally, it resolves with the value returned by pageFunction.
In this case, we are just returning the text for h1 tag.
*/
heading = await page.$eval(HEADING_SELECTOR, heading => heading.innerText);
expect(heading).to.eql('Spotify Playlist Creator');
});
it('should not display ErrorModal', async function () {
const ERROR_MODAL_SELECTOR = '.ErrorModal';
page.waitForSelector(ERROR_MODAL_SELECTOR)
// The method runs document.querySelectorAll within the page. If no elements match the selector, the return value resolves to []
expect(await page.$$(ERROR_MODAL_SELECTOR)).to.be.deep.equal([])
});
it('should be displaying login button', async function () {
const LOGIN_BUTTON_SELECTOR = 'button';
let loginBtn;
page.waitForSelector(LOGIN_BUTTON_SELECTOR);
loginBtn = await page.$(LOGIN_BUTTON_SELECTOR)
const btnText = await page.evaluate(loginBtn => loginBtn.textContent, loginBtn);
expect(btnText).to.equal("Login to Spotify");
});
// DOES NOT WORK!!!
it('should click login button', async function () {
const LOGIN_BUTTON_SELECTOR = 'button';
let loginBtn;
page.waitForSelector(LOGIN_BUTTON_SELECTOR);
loginBtn = await page.$(LOGIN_BUTTON_SELECTOR)
await loginBtn.click();
console.log(loginBtn, "button has been clicked")
expect(page.url()).to.include("https://accounts.spotify.com/en/login?");
});
})
答:
0赞
karalkal
10/24/2023
#1
我首先用赛普拉斯达到了预期的效果:
cy.on("url:changed", (newUrl) => {
expect(newUrl).to.contain([whatever-it-should-contain])
如果我没记错的话,Page.waitForNavigation() 方法在 Puppeteer 中也做同样的事情。 我不是一只快乐的兔子,因为我浪费了几个小时来弄清楚这一点 - 我从没想过一个名为“waitForNavigation”的方法会等待页面导航到新的 URL......当然,这完全是我的错。 正确的测试如下:
it.only('should click login button', async function () {
const LOGIN_BUTTON_SELECTOR = 'button';
let loginBtn;
page.waitForSelector(LOGIN_BUTTON_SELECTOR);
loginBtn = await page.$(LOGIN_BUTTON_SELECTOR)
await loginBtn.click();
await page.waitForNavigation();
expect(page.url()).to.include("https://accounts.spotify.com/en/login?");
});
评论
waitForTimeout
接受一个数字作为其参数,而不是字符串。也就是说,超时一开始就不好用。你可能想在这里使用。可能还有其他问题,但如果没有一个最小的可重复示例,除了快速的现场抽查之外,很难提供太多的东西。await loginBtn.click();
await page.waitForTimeout(HEADING_SELECTOR);
waitForSelector
await
await
await