1

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.

TypeScript error

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

2 Answers 2

1

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/*"
  ]
}
Sign up to request clarification or add additional context in comments.

10 Comments

Thank for the answer. I feel like this is extremely close to the solution, however, this causes an error Duplicate identifier 'BoundFunction' I was snooping around this same BoundFunction yesterday, but I'm not really sure what all the infer + conditionals mean in this definition, my TypeScript isn't that advanced yet. Perhaps I need to investigate extending the existing definition.
Can you update the answer where the error comes from + the stack trace then?
I'm not getting much of a stack trace, my IDE is only showing an error: TS2300: Duplicate identifier 'BoundFunction' on the line . get-queries-for-element.d.ts(3, 13): 'BoundFunction' was also declared here. This file node_modules/@testing-library/dom/types/get-queries-for-element.d.ts already contains a BoundFunction definition.I'm reading up on infer and extends usage with the conditionals to try an understand this a bit better.
Can you share your tsconfig.json then?
Sure, I added it to the original question, right at the bottom. I need to add that this is a Gatsby theme, so it uses gatsby-plugin-typescript, the tsconfig.js is purely there for the IDE, Gatsby uses it's own internal configuration as far as I'm aware.
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.