如何使用 React 测试库在古腾堡编辑器中使用 Puppeteer 测试元素的出现/消失?

问题描述

我有以下设置:

我在测试 GB 编辑器中元素的出现和消失时遇到问题。我现在知道扩展断言不适用于 Puppeteer。我只是不知道要测试什么。当我以交互模式运行测试时,我可以看到一切正常,但我没有得到正确的结果。查询的结果只是一个空对象。这是我的代码片段:

import {
    enablePageDialogAccept,setbrowserViewport,createNewPost,opendocumentSettingsSidebar,insertBlock,loginUser,} from '@wordpress/e2e-test-utils';

import '@testing-library/jest-dom/extend-expect';
import { getDocument,queries,waitFor } from 'pptr-testing-library';

import { clearPuppeteerbrowser } from '../../../lib/helpers/e2eHelpers';

const {
    getByRole,getByLabelText,getBydisplayValue,getByText,queryByLabelText,findByRole,findByLabelText,findByText,findAllByText,} = queries;

describe('CVGB Button block',() => {
  // Initialize vars within suite's scope
  let $document;
  let $editorSettings;
  let $editorContent;

  // Enable page dialog before running any tests
  beforeAll(async () => {
    await clearPuppeteerbrowser();
    await loginUser();
    await enablePageDialogAccept();
  });

  // Wait for creating a new post before running each of the tests
  beforeEach(async () => {
    await createNewPost();
    $document = await getDocument(page);

    // we want to look for Sidebar region only
    $editorSettings = await getByRole($document,'region',{ name: 'Editor settings' });

    // the same for the editor content,so we don't get repeated components from all the document
    $editorContent = await getByRole($document,{ name: 'Editor content' });
  });

  it('should be able to unset a Link when URL is already set',async () => {
    await insertBlock('CVGB Button');
    await opendocumentSettingsSidebar();

    const $linkButton = await findByRole($document,'button',{
      name: 'Link',});
    await $linkButton.click();

    const $URLInput = await findByRole($document,'comboBox',{
      name: 'URL',});
    await $URLInput.click();
    await $URLInput.type('https://www.google.es');
    await $URLInput.press('Enter');

    await waitFor(() => {
      expect(
        findByLabelText($document,'Currently selected',{
          exact: false,})
      ).toBeInTheDocument();
    });
  });
});

这是我看到的错误

Result of the test above

测试下方完整的 Node 错误消息如下:

(node:41767) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
    at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:208:63
    at new Promise (<anonymous>)
    at CDPSession.send (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:207:16)
    at ExecutionContext._evaluateInternal (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:200:50)
    at ExecutionContext.evaluateHandle (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:151:21)
    at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/lib/index.ts:101:8
    at Generator.next (<anonymous>)
    at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:8:71
    at new Promise (<anonymous>)
    at Object.<anonymous>.__awaiter (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:4:12)
(node:41767) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block,or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection,use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 908)

编辑:回应Caleb Eby's asnwer

我认为这就是 waitFor() 的用途……但是如果我只添加 await findByLabelText(),我会收到一个错误

SyntaxError: /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/blocks/button/test/buttonBlock.e2e.spec.js: Unexpected reserved word 'await'. (126:16)

如果我把它改成:

        await waitFor(async () => {
            expect(
                await findByLabelText($document,{
                    exact: false,})
            ).toBeInTheDocument();
        });

运行测试需要很长时间并以错误结束:

    expect(received).toBeInTheDocument()

    received value must be an HTMLElement or an SVGElement.
    Received has type:  object
    Received has value: 
    {
        "_client": {
            "_callbacks": [Map],"_connection": [Connection],"_sessionId": "9E13F5776A59D1DD6A177F48A9D1A543","_targettype": "page","emitter": [Object],"eventsMap": [Map]
        },"_context": {
            "_client": [CDPSession],"_contextId": 17,"_world": [DOMWorld]
        },"_disposed": false,"_frameManager": {
            "_client": [CDPSession],"_contextIdToContext": [Map],"_frames": [Map],"_isolatedWorlds": [Set],"_mainFrame": [Frame],"_networkManager": [NetworkManager],"_page": [Page],"_timeoutSettings": [TimeoutSettings],"_page": {
            "_accessibility": [Accessibility],"_client": [CDPSession],"_closed": false,"_coverage": [Coverage],"_emulationManager": [EmulationManager],"_fileChooserInterceptors": [Set],"_frameManager": [FrameManager],"_javascriptEnabled": true,"_keyboard": [Keyboard],"_mouse": [Mouse],"_pageBindings": [Map],"_screenshottaskQueue": [ScreenshottaskQueue],"_target": [Target],"_touchscreen": [Touchscreen],"_tracing": [Tracing],"_viewport": [Object],"_workers": [Map],"_remoteObject": {
            "className": "HTMLdivelement","description": "div.block-editor-link-control__search-item.is-current","objectId": "-193265238525024879.17.113","subtype": "node","type": "object"
        }
    }

这实际上可能是解决方案的罪魁祸首,但是对此进行测试的正确方法是什么(而不是 toBeInTheDocument())?

解决方法

看起来您在 ^ 块中缺少一个 await,因为 findByLabelText 返回一个承诺:

expect