Home > Back-end >  Cypress custom find command is not chainable
Cypress custom find command is not chainable

Time:03-02

I want to create a custom Cypress find command like so to utilize a data-test attribute.

cypress/support/index.ts

declare global {
  namespace Cypress {
    interface Chainable {
      /**
       * Custom command to get a DOM element by data-test attribute.
       * @example cy.getByTestId('element')
       */
       getByTestId(selector: string): Chainable<JQuery<HTMLElement>>;

      /**
       * Custom command to find a DOM element by data-test attribute.
       * @example cy.findByTestId('element')
       */
      findByTestId(selector: string): Chainable<JQuery<HTMLElement>>;
    }
  }
}

cypress/support/commands.ts

Cypress.Commands.add('getByTestId', (selector, ...args) => {
  return cy.get(`[data-test=${selector}]`, ...args);
});

Cypress.Commands.add(
  'findByTestId',
  { prevSubject: 'element' },
  (subject, selector) => {
    return subject.find(`[data-test=${selector}]`);
  }
);

Here subject is of type JQuery<HTMLElement> and not Cypress.Chainable<JQuery<HTMLElement>>, so subject.find is not chainable with others methods.

I get the following errors from Typescript.

No overload matches this call.
  Overload 1 of 4, '(name: "findByTestId", options: CommandOptions & { prevSubject: false; }, fn: CommandFn<"findByTestId">): void', gave the following error.
  Overload 2 of 4, '(name: "findByTestId", options: CommandOptions & { prevSubject: true | keyof PrevSubjectMap<unknown> | ["optional"]; }, fn: CommandFnWithSubject<"findByTestId", unknown>): void', gave the following error.
  Overload 3 of 4, '(name: "findByTestId", options: CommandOptions & { prevSubject: "element"[]; }, fn: CommandFnWithSubject<"findByTestId", JQuery<HTMLElement>>): void', gave the following error.ts(2769)
cypress.d.ts(22, 5): The expected type comes from property 'prevSubject' which is declared here on type 'CommandOptions & { prevSubject: false; }'

Desired usage

cy.getByTestId('some-element')
  .findByTestId('some-test-id')
  .should('have.text', 'Text');

How could I fix this?

CodePudding user response:

I may be off the mark, but subject.find(...) is using jQuery find.

Perhaps you want cy.wrap(subject).find(...) which should yield the Cypress.Chainable wrapper.

CodePudding user response:

Had to add a cy.wrap command around the JQuery element like so.

Cypress.Commands.add(
  'findByTestId',
  { prevSubject: 'element' },
  (subject, selector) => {
    return cy.wrap(subject).find(`[data-test=${selector}]`);
  }
)
  • Related