我知道剧作家有自动等待。
我有一个测试,有时点击有效,有时则无效。下面是代码。
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
错误:
expect(收到).toHaveURL(预期) 预期字符串:“https://website.com/login/” 收到字符串:“https://website.com”
这是一段带有登录按钮的 HTML
<span data-v-154d6ddf="" class="absolute-top-right">
<div class="row justify-end q-gutter-x-sm q-pt-lg q-px-sm">
<div class="col-auto">
<a tabindex="0" type="button" href="/login/potential" role="link" class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-white q-btn--actionable q-focusable q-hoverable q-btn--no-uppercase q-btn--wrap">
<span class="q-focus-helper" tabindex="-1"></span>
<span class="q-btn__wrapper col row q-anchor--skip">
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
<span>Log in</span>
</span>
</span>
</a>
</div>
<div class="col-auto">
<a tabindex="0" type="button" href="/signup" role="link" class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable q-btn--no-uppercase q-btn--wrap">
<span class="q-focus-helper"></span>
<span class="q-btn__wrapper col row q-anchor--skip">
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
<span>Sign up</span>
</span>
</span>
</a>
</div>
<div class="col-auto">
<label for="f_2334a082-8df9-41a7-9ca0-403e5ce7c237" class="q-field q-validation-component row no-wrap items-start q-select q-field--auto-height q-select--without-input q-select--without-chips q-field--outlined q-field--float q-field--labeled" style="min-width:120px;max-height:20px">
<div class="q-field__inner relative-position col self-stretch column justify-center">
<div tabindex="-1" class="q-field__control relative-position row no-wrap">
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
<div id="translate" class="q-field__native row items-center">
<span>English</span>
<div id="f_2334a082-8df9-41a7-9ca0-403e5ce7c237" tabindex="0" class="no-outline"></div>
</div>
<div class="q-field__label no-pointer-events absolute ellipsis">Translate</div>
</div>
<div class="q-field__append q-field__marginal row no-wrap items-center q-anchor--skip">
<i aria-hidden="true" role="presentation" class="q-select__dropdown-icon fal fa-caret-down q-icon notranslate"></i>
</div>
</div>
</div>
</label>
</div>
</div>
</span>
我尝试了这种变体(见下文),看起来它失败的频率较低,但仍然不能 100% 工作。
我也尝试过
.click({force: true})
。第三次运行失败。
我是测试自动化的新手。刚刚开始学习剧作家。
我将不胜感激任何意见/建议。 谢谢你。
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
const loginBtn = page.getByRole('link', { name: 'Log in' });
expect(await loginBtn.evaluate(node => node.isConnected)).toBe(true) ;
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
“您应该在点击按钮后等待,然后再验证网址。”这是来自 @jaky-ruby 的建议
我试过这个代码
test('test2', async ({ page }) => {
await page.goto('https://website.com/');
// Note that Promise.all prevents a race condition
// between clicking and expecting navigation result.
const [response] = await Promise.all([
page.getByRole('link', { name: 'Log in' }).click(),
page.waitForNavigation({ url: 'https://website.com/login' }),
]);
await expect(page).toHaveURL('https://website/login');
...
});
我在 Cypress 中创建了类似的测试。 这是代码
describe("Login", () => {
beforeEach(() => {
cy.visit(baseUrl);
});
it.only("Login page should open", () => {
//does not help: cy.wait(3000);
cy.get('a[href*="login"]').click();
//does not help: cy.get(':nth-child(1) > .q-btn > .q-btn__wrapper > .q-btn__content > span').click();
//does not help: cy.get('#q-app > div > span > div > div:nth-child(1) > a > span.q-btn__wrapper.col.row.q-anchor--skip > span').click();
cy.url().should("eq", authUrl.replace("env", env) + "/login/potential");
});
});
如您所见,我尝试了定位器的不同变体。有趣的是 Cypress 显示了这个错误。不确定这是否与剧作家测试中出现的问题相同。
CypressError
4050 毫秒后超时重试:cy.click() 失败,因为此元素:...被另一个元素覆盖:
我试图在 DOM 中找到该元素,但它不在那里。
我不明白的另一件事是,当我在 Cypress 中选择“单击”步骤并使用选择器选择我的按钮时,它会向我显示选择器
cy.get('[data-layer="Content"]')
。同样,当我尝试在 DOM 中搜索它时,它不在那里。
我使用 Trace Viewer 检查了 Playwright 中的每个步骤。 有趣的。日志显示 Playwright 正在等待元素可见且稳定。但是,在附加页面上,“登录”和“注册”按钮均不可见且仍在加载(事实证明您可以检查它。这不仅仅是静态屏幕截图)。我认为,在这个例子中,Playwright 的自动等待可能不够好。可能,元素实际上并不稳定并且仍在加载,但 Playwright 执行的单击不起作用。 现在问题是,“我可以做一些额外的等待来确定该元素已加载且稳定吗?”
好吧,看起来我找到了~~解决方案~~一种让我的测试不那么不稳定的方法。
测试有时仍然会失败。我认为,我添加的额外 2 个等待只会为元素加载提供更多时间,因此在大多数情况下,这可能足以让按钮达到稳定状态。这就是点击有效的原因。请注意,在下面的屏幕截图中,“networkidle”为 1.4 秒
这是最终代码
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
await page.waitForLoadState('networkidle'); // <- until there are no network connections for at least 500 ms.
await page.getByRole('link', { name: 'Log in' }).waitFor(); // <- wait for element
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
在这里分享我一路上发现的一些有趣的链接
waitFor() 等待元素可见,这已经由 Playwright 完成了。所以在 click() 方法之前添加它是没有意义的。 我认为这个问题与渲染有关,至少看起来是我的项目的问题。这是水合作用的问题,之后有一段时间页面似乎已完全加载并可交互,但直到执行客户端 JavaScript 并附加事件处理程序后才出现。当时编剧做出点击动作,没用。