简体   繁体   中英

Creating custom queries with React testing-library and TypeScript

I'm trying to create a custom query for Testing Library in TypeScript? I intend to use this with a React project.

The query simply gets the first th cells in the tbody of the container:

// 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
};

Here the query is added to a custom render function:

// 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 };

Here's a very simple usage example:

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

However TypeScript complains as follows:

TS2554: Expected 1-3 arguments, but got 0.

打字稿错误

If I ignore the error by adding // @ts-ignore I can confirm that the custom query works, it's just TS that's a bit unhappy.

Is this something that can be fixed by adding a d.ts file, the documentation on Testing Library isn't very clear how to resolve the TypeScript approach of adding custom queries.

Here's my tsconfig.json for reference:

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

In the type definition @testing-library/dom always requires text as the 1st option (despite allowing to input as undefined ). However, I'm not to sure if this is still right with your case with a custom query. Apparently, you've done successfully without any issue in case of having no argument specified. (of course baz() // <=> baz(undefined) ).

Anyway, To answer your question about if there's a way to override the type, so the answer is yes. Here's the way you can achieve the goal:

Create your types at the root dir which a custom types for your repo, then add a file like testing-library.dom.d.ts with following content:

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;
}

Keep in mind, include custom files in your tsconfig.json :

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

I had the same error and after updating "@testing-library/dom" package to the current latest ( ^8.17.1 ) solved it for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM