笑话错误:“您的焦点陷阱必须始终具有至少一个包含一个tabbable节点的容器。

发布于 2025-02-10 14:07:38 字数 2634 浏览 1 评论 0 原文

我正在用玩笑来编写React组件的测试。我无法在组件测试中修复错误。我试图将重点放在测试代码中:

await waitFor(() => expect(screen.getByTestId('continue')).toHaveFocus());

但是它不起作用。如何解决此错误?

这是组件代码:

function SuccessCommentAddPopup({onSuccessComment}: SuccessCommentAddPopupProps): JSX.Element {
 
  return (
    <AriaModal
      titleText='add comment success'
      initialFocus="#continue"
    >
      <div style={{position: 'relative', width: '550px', height: '410px', marginBottom: '50px'}}>
        <div className={style.modal}>
          <div className={style.modalWrapper}>
            <div className={style.modalOverlay} data-close-modal></div>
            <div className={style.modalContent}>
              <svg className={style.modalIcon} width="26" height="20" aria-hidden="true">
                <use xlinkHref="#icon-success"></use>
              </svg>
              <p className={style.modalMessage}>Thank's a lot!</p>
              <div className={style.modalButtonContainer}>
                <button
                  id='continue'
                  data-testid='continue'
                  className={style.modalButton}
                  onClick={()=>{
                    onSuccessComment(false);
                  }}
                >
                Close
                </button>
              </div>
              <button
                className={style.modalCloseBtn}
                type="button"
                aria-label="Close"
                onClick={()=>{
                  onSuccessComment(false);
                }}
              >
                <span className={style.buttonCrossIcon}>
                </span><span className={style.modalCloseBtninteractiveArea}></span>
              </button>
            </div>
          </div>
        </div>
      </div>
    </AriaModal>
  );
}

export default SuccessCommentAddPopup;

这是测试代码:

const history = createMemoryHistory();
history.push('/guitars/1');


describe('Component: SuccessCommentAddPopup', () => {
  it('Компонент отрисовывается корректно', async () => {
    render(
      <HistoryRouter history={history}>
        <SuccessCommentAddPopup
          onSuccessComment={jest.fn()}
        />
      </HistoryRouter>,
    );
    await waitFor(() => expect(screen.getByTestId('continue')).toHaveFocus());
    expect(screen.getByText('Спасибо за ваш отзыв!')).toBeInTheDocument();
  });
});

I'm using Jest to write tests for React Components. I can't fix a bug in a component test. I tried to add focus on the element to the test code:

await waitFor(() => expect(screen.getByTestId('continue')).toHaveFocus());

But it didn't work. How to solve this error?

This is the component code:

function SuccessCommentAddPopup({onSuccessComment}: SuccessCommentAddPopupProps): JSX.Element {
 
  return (
    <AriaModal
      titleText='add comment success'
      initialFocus="#continue"
    >
      <div style={{position: 'relative', width: '550px', height: '410px', marginBottom: '50px'}}>
        <div className={style.modal}>
          <div className={style.modalWrapper}>
            <div className={style.modalOverlay} data-close-modal></div>
            <div className={style.modalContent}>
              <svg className={style.modalIcon} width="26" height="20" aria-hidden="true">
                <use xlinkHref="#icon-success"></use>
              </svg>
              <p className={style.modalMessage}>Thank's a lot!</p>
              <div className={style.modalButtonContainer}>
                <button
                  id='continue'
                  data-testid='continue'
                  className={style.modalButton}
                  onClick={()=>{
                    onSuccessComment(false);
                  }}
                >
                Close
                </button>
              </div>
              <button
                className={style.modalCloseBtn}
                type="button"
                aria-label="Close"
                onClick={()=>{
                  onSuccessComment(false);
                }}
              >
                <span className={style.buttonCrossIcon}>
                </span><span className={style.modalCloseBtninteractiveArea}></span>
              </button>
            </div>
          </div>
        </div>
      </div>
    </AriaModal>
  );
}

export default SuccessCommentAddPopup;

This is the test code:

const history = createMemoryHistory();
history.push('/guitars/1');


describe('Component: SuccessCommentAddPopup', () => {
  it('Компонент отрисовывается корректно', async () => {
    render(
      <HistoryRouter history={history}>
        <SuccessCommentAddPopup
          onSuccessComment={jest.fn()}
        />
      </HistoryRouter>,
    );
    await waitFor(() => expect(screen.getByTestId('continue')).toHaveFocus());
    expect(screen.getByText('Спасибо за ваш отзыв!')).toBeInTheDocument();
  });
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白馒头 2025-02-17 14:07:38

@Ararat是正确的。我通过嘲笑tabbable: https://github.com/focus-trap /tabbable#testing-in-jsdom

添加了:./< strong> mocks/tabable.js,以下内容:

// __mocks__/tabbable.js

const lib = jest.requireActual('tabbable');

const tabbable = {
   ...lib,
   tabbable: (node, options) => lib.tabbable(node, { ...options, displayCheck: 'none' }),
   focusable: (node, options) => lib.focusable(node, { ...options, displayCheck: 'none' }),
   isFocusable: (node, options) => lib.isFocusable(node, { ...options, displayCheck: 'none' }),
   isTabbable: (node, options) => lib.isTabbable(node, { ...options, displayCheck: 'none' }),
};

module.exports = tabbable;

我花了很多时间来弄清楚这一点,这就是为什么我分享!我在VUE 3项目中使用了@Vueus的Usefocustrap,由于缺少此缺少,我的Vue-testing-library组件测试破裂了!

@Ararat is correct. I solved this by mocking out tabbable: https://github.com/focus-trap/tabbable#testing-in-jsdom

added: ./mocks/tabable.js with the following:

// __mocks__/tabbable.js

const lib = jest.requireActual('tabbable');

const tabbable = {
   ...lib,
   tabbable: (node, options) => lib.tabbable(node, { ...options, displayCheck: 'none' }),
   focusable: (node, options) => lib.focusable(node, { ...options, displayCheck: 'none' }),
   isFocusable: (node, options) => lib.isFocusable(node, { ...options, displayCheck: 'none' }),
   isTabbable: (node, options) => lib.isTabbable(node, { ...options, displayCheck: 'none' }),
};

module.exports = tabbable;

I spent a lot of time figuring this out, thats why im sharing! I was using useFocusTrap from @vueUs in a vue 3 project and my vue-testing-library component tests broke because of this missing!

不喜欢何必死缠烂打 2025-02-17 14:07:38

您需要模拟 Tabbable 模块。检查此 link

You need to mock tabbable module. Check this link

你怎么这么可爱啊 2025-02-17 14:07:38

您需要在 __模拟__ 文件夹中创建tabbanle.js文件,现在,如果您没有文件夹,则iDe inde inde in for __ test test __ test __ test __ 在我的存储库中,我会在我的存储库中添加了该文件夹 src/server/models/__模拟__/tabbable.js
是的,它类似于其他答案,但是在哪里丢失了文件夹信息,我花了很长时间才能弄清楚它,因此

在此处添加以下代码。

// __mocks__/tabbable.js

const lib = jest.requireActual('tabbable');

const tabbable = {
...lib,
tabbable: (node, options) => lib.tabbable(node, { 
 ...options, displayCheck: 'none' }),
 focusable: (node, options) => lib.focusable(node, { 
 ...options, displayCheck: 'none' }),
 isFocusable: (node, options) => lib.isFocusable(node, { 
 ...options, displayCheck: 'none' }),
 isTabbable: (node, options) => lib.isTabbable(node, { 
...options, displayCheck: 'none' }),
 };

 module.exports = tabbable;

只需保存文件并再次运行测试,错误就会神奇地消失。
更新后,我还写了有关所有其他笑话错误的帖子,您可以在此处查看 https:> https:> https:> https:> https: //medium.com/@arianallami/jest-update-466f08181d06

You need to create tabbanle.js file inside your __mocks__ folder, now if you do not have the folder in you IDE look for __test__ folder in my repository I added the folder in the src/server/models/__mocks__/tabbable.js
yes it is similar to the other answer but where do create the folder information was missing and it took me long time to figure it out hence adding here

And add the below code in that file.

// __mocks__/tabbable.js

const lib = jest.requireActual('tabbable');

const tabbable = {
...lib,
tabbable: (node, options) => lib.tabbable(node, { 
 ...options, displayCheck: 'none' }),
 focusable: (node, options) => lib.focusable(node, { 
 ...options, displayCheck: 'none' }),
 isFocusable: (node, options) => lib.isFocusable(node, { 
 ...options, displayCheck: 'none' }),
 isTabbable: (node, options) => lib.isTabbable(node, { 
...options, displayCheck: 'none' }),
 };

 module.exports = tabbable;

just save the file and run your tests again and the error would have magically disappeared.
I have also written a post on all other jest errors after the update you can check here here https://medium.com/@arianallami/jest-update-466f08181d06

-柠檬树下少年和吉他 2025-02-17 14:07:38

我们应该找到此功能的哪个分支返回true

在我的情况下

if (isNodeAttached(node)) {
  // this works wherever the node is: if there's at least one client rect, it's
  //  somehow displayed; it also covers the CSS 'display: contents' case where the
  //  node itself is hidden in place of its contents; and there's no need to search
  //  up the hierarchy either
  return !node.getClientRects().length;
}

,我们需要像这样嘲笑它

const getClientRects = HTMLElement.prototype.getClientRects
HTMLElement.prototype.getClientRects = function () {
  return {
    ...getClientRects.apply(this),
    length: 1
  }
}

We should find which branch of this function returns true https://github.com/focus-trap/tabbable/blob/master/src/index.js#L367

In my case it was

if (isNodeAttached(node)) {
  // this works wherever the node is: if there's at least one client rect, it's
  //  somehow displayed; it also covers the CSS 'display: contents' case where the
  //  node itself is hidden in place of its contents; and there's no need to search
  //  up the hierarchy either
  return !node.getClientRects().length;
}

So, we need to mock it like so

const getClientRects = HTMLElement.prototype.getClientRects
HTMLElement.prototype.getClientRects = function () {
  return {
    ...getClientRects.apply(this),
    length: 1
  }
}
南街女流氓 2025-02-17 14:07:38

对于Vite,您可以在直接安装组件时指定,按此评论

<FocusTrap
  focusTrapOptions={{
    ...,
    tabbableOptions: {
      displayCheck: TEST_ENV ? 'none' : 'whatever you normally set it to, or undefined for the default'
    }
  }}
>
  <button>I'm trapped</button>
</FocusTrap>

不过,这对Vite的依赖关系无济于事。

For vite, you can specify when mounting the component directly, as per this comment:

<FocusTrap
  focusTrapOptions={{
    ...,
    tabbableOptions: {
      displayCheck: TEST_ENV ? 'none' : 'whatever you normally set it to, or undefined for the default'
    }
  }}
>
  <button>I'm trapped</button>
</FocusTrap>

This won't help with dependencies of dependencies in vite though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文