我正在尝试使用客户端函数来访问页面上子元素中的值,不一定是本示例中的值,而是那些使用提供的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;
    });

10-06 07:43