【问题标题】:Creating custom queries with React testing-library and TypeScript使用 React 测试库和 TypeScript 创建自定义查询
【发布时间】:2021-04-26 10:17:11
【问题描述】:

我正在尝试在 TypeScript 中为 Testing Library 使用 create a custom query?我打算在 React 项目中使用它。

查询只是获取容器tbody 中的第一个th 单元格:

// all-table-headings.ts - contains the custom query

import { buildQueries } from '@testing-library/dom';

const queryAllTableHeadings = (container: HTMLElement): HTMLElement[] =>
  Array.from(container.querySelectorAll('thead th'));

const getMultipleError = () => '...';
const getMissingError = () => 'Could not find any table headings!';

const [
  queryTableHeadings, getAllTableHeadings, getTableHeadings, findAllTableHeadings, findTableHeadings
] = buildQueries(queryAllTableHeadings, getMultipleError, getMissingError);

export {
  queryTableHeadings, getAllTableHeadings, getTableHeadings, findAllTableHeadings, findTableHeadings
};

这里将查询添加到自定义渲染函数中:

// index.ts - exports a custom render function

import { queries, render } from '@testing-library/react';
import * as allTableHeadings from './all-table-headings';
import * as allCellsAtRow from './all-cells-at-row';

const customRender = (ui, options = {}) =>
  render(ui, {
    queries: {
      ...queries,
      ...allTableHeadings,
      ...allCellsAtRow
    },
    ...options
  });

export * from '@testing-library/react';
export { customRender as render };

这是一个非常简单的用法示例:

const TestComponent = () => <div>Test Component</div>;
const { getAllTableHeadings } = render(<PropsTable component={ TestComponent }/>);
const headings = getAllTableHeadings();

然而 TypeScript 抱怨如下:

TS2554:预期有 1-3 个参数,但得到了 0 个。

如果我通过添加 // @ts-ignore 来忽略错误,我可以确认自定义查询有效,只是 TS 有点不高兴。

这是可以通过添加 d.ts 文件来解决的问题吗,测试库上的文档不是很清楚如何解决 TypeScript 添加自定义查询的方法。

这是我的 tsconfig.json 供参考:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "jsx": "react"
  }
}

【问题讨论】:

    标签: reactjs typescript react-testing-library testing-library


    【解决方案1】:

    在类型定义中@testing-library/dom 始终需要text 作为第一个选项(尽管允许输入为undefined)。但是,我不确定这是否仍然适用于您的自定义查询。显然,在没有指定参数的情况下,您已经成功完成,没有任何问题。 (当然是baz() // &lt;=&gt; baz(undefined))。

    无论如何,要回答您关于是否有办法覆盖类型的问题,所以答案是肯定的。以下是实现目标的方法:

    在根目录中创建您的types,为您的存储库自定义类型,然后添加类似testing-library.dom.d.ts 的文件,其内容如下:

    types/testing-library.dom.d.ts

    import "@testing-library/dom";
    
    declare module "@testing-library/dom" {
      // This is the function creates the output for each query function
      // we changed `text` to become optional `text?` in `(text?: P, options?: Q, waitForElementOptions?: W) => R`
      export type BoundFunction<T> = T extends (
        attribute: string,
        element: HTMLElement,
        text: infer P,
        options: infer Q
      ) => infer R
        ? (text: P, options?: Q) => R
        : T extends (
            a1: any,
            text: infer P,
            options: infer Q,
            waitForElementOptions: infer W
          ) => infer R
        ? (text?: P, options?: Q, waitForElementOptions?: W) => R
        : T extends (a1: any, text: infer P, options: infer Q) => infer R
        ? (text: P, options?: Q) => R
        : never;
    }
    
    

    请记住,include 自定义文件在您的 tsconfig.json 中:

    {
      // ...
      "include": [
        "types/*"
      ]
    }
    

    【讨论】:

    • 感谢您的回答。我觉得这非常接近解决方案,但是,这会导致错误Duplicate identifier 'BoundFunction' 我昨天在同一个 BoundFunction 周围窥探,但我不确定所有推断 + 条件在此定义中的含义,我的 TypeScript 是还没有那么先进。也许我需要研究扩展现有定义。
    • 你能更新错误来自的答案+堆栈跟踪吗?
    • 我没有得到太多堆栈跟踪,我的 IDE 只显示错误:TS2300: Duplicate identifier 'BoundFunction' on the line get-queries-for-element.d.ts(3, 13): 'BoundFunction' was also declared here. 这个文件node_modules/@testing-library/dom/types/get-queries-for-element.d.ts 已经包含一个BoundFunction 定义。我正在阅读inferextends 的使用情况,以尝试更好地理解这一点。
    • 那你能分享你的 tsconfig.json 吗?
    • 当然,我将它添加到原始问题的底部。我需要补充一点,这是一个 Gatsby 主题,所以它使用 gatsby-plugin-typescript,tsconfig.js 纯粹用于 IDE,据我所知,Gatsby 使用它自己的内部配置。
    猜你喜欢
    • 2020-01-15
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2021-04-21
    • 2021-06-07
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多