我正在尝试使用客户端函数来访问页面上子元素中的值,不一定是本示例中的值,而是那些使用提供的testcafe选择器很难找到的值。
在定义页面对象模型时,我希望能够访问多个iFrame模态上的“下一步”,“后退”和“保存”按钮,根据模态 View ,它们可以在DOM上具有不同的位置,并且没有ID(产品是旧的)。
但是它们确实遵循类似的模式,它们都是span的子元素,并且包含带有名称的Display文本和标题,可以通过chrome Dev Tools Console通过类似于以下内容的方式访问它们
Array.from(document.querySelectorAll('span')).find(el => el.textContent === "Next")
但是,当我尝试在testcafe中将其作为客户端函数调用时,出现错误,以下是基于我的方法但针对testcafe网站的示例,该示例给出了相同的错误。
import { Selector } from 'testcafe';
import { ClientFunction } from 'testcafe';
fixture `Client Function`
.page `https://devexpress.github.io/testcafe/documentation/test-api/selecting-page-elements/selectors/functional-style-selectors.html`;
const query = ClientFunction(() => Array.from(document.querySelectorAll('a')).find(el => el.textContent === "Filter DOM Nodes"));
test('Test query', async t => {
const queryResult = await query();
await t
.click(Selector(queryResult))
.wait(1500);
});
这给我带来的错误对我来说是个神秘的东西:
1) An error occurred in ClientFunction code:
ReferenceError: _from2 is not defined
Browser: Chrome 71.0.3578 / Mac OS X 10.13.6
6 | .page
`https://devexpress.github.io/testcafe/documentation/test-api/selecting-page-elements/selectors/functional-style-selectors.html`;
7 |
8 |const query = ClientFunction(() =>
Array.from(document.querySelectorAll('a')).find(el => el.textContent
=== "Filter DOM Nodes"));
9 |
10 |test('Login and register user', async t => {
> 11 | const queryResult = await query();
12 | await t
13 | .click(Selector(queryResult))
14 | .wait(1500);
15 |});
16 |
at query (/Users/david/Documents/testcafe/demo/query.js:11:33)
at test (/Users/david/Documents/testcafe/demo/query.js:10:1)
at markeredfn
(/usr/local/lib/node_modules/testcafe/src/api/wrap-test-function.js:17:28)
at <anonymous>
(/usr/local/lib/node_modules/testcafe/src/api/wrap-test-function.js:7:5)
at fn
(/usr/local/lib/node_modules/testcafe/src/test-run/index.js:239:19)
at TestRun._executeTestFn
(/usr/local/lib/node_modules/testcafe/src/test-run/index.js:235:38)
at _executeTestFn
(/usr/local/lib/node_modules/testcafe/src/test-run/index.js:284:24)
1/1 failed (5s)
有谁知道这是合法错误还是实现错误?谢谢-任何指针也非常欢迎!
最佳答案
您可以这样重写ClientFunction:
const query = ClientFunction(() => {
const results = [];
const allLinks = document.querySelectorAll('a');
allLinks.forEach(link => results.push(link));
const foundElement = results.find(el => el.textContent === "Filter DOM Nodes");
return foundElement;
});
但随后您将收到另一个错误:
ClientFunction cannot return DOM elements. Use Selector functions for this purpose.
ClientFunction内部的代码在浏览器中执行。
调用此ClientFunction并获取其结果的代码在浏览器外部的NodeJS进程中执行。
您试图实现的目标称为对象编码。您试图将位于浏览器进程中的DOM对象转移到另一个单独的进程中。这只能通过序列化来实现,但是DOM对象不可序列化。
ClientFunction内部的return语句必须返回POJO(普通的旧Javascript对象)。
您可以通过使用Selector对象来实现相同的目的:
const nextButton = Selector('span')
.find('a')
.withAttribute('title', 'NEXT')
.withText('NEXT');
await t.click(nextButton);
如果您需要除属性和textContent之外的特殊过滤,则可以这样编写选择器:
const nextButton = Selector('span')
.find('a')
.filter((link) => {
if (/* some condition processed on link element */) {
// this link element is the one to be clicked
return true;
}
return false;
});