import "@testing-library/cypress/add-commands"; interface ItemLocator { name: T; item: string; index?: never; } interface IndexLocator { name: T; index: number; item?: never; } type Locator = string | ItemLocator | IndexLocator; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Chainable { /** * Get an element by data-test attribute. * @example * cy.getId("print-button") */ getId( id: Locator | Array>, options?: Partial, ): Chainable>; } } } // @ts-ignore Cypress.SelectorPlayground.defaults({ selectorPriority: ["data-test"], onElement: (element: JQuery) => { const test = element.data("test"); if (!test) { return ""; } const parents = Array.from(element.parents("[data-test]")) .reverse() .map((parent) => { const id = parent.dataset["test"]; const itemId = parent.dataset["test-item"]; if (itemId) { return `{ name: "${id}", item: "${itemId}" }`; } return `"${id}"`; }) .join(", "); const testItem = element.data("test-item"); const selector = testItem ? `{ name: "${test}", item: "${testItem}" }` : `"${test}"`; return parents ? `[${parents}, ${selector}]` : `${selector}`; }, }); Cypress.Commands.add( "getId", ( locators: Locator | Array>, options: Partial = {}, ) => { locators = Array.isArray(locators) ? locators : [locators]; return cy.get( locators .map((locator) => { if (typeof locator === "string") { return `[data-test=${locator}]`; } if (locator.item !== undefined) { return `[data-test=${locator.name}][data-test-item=${locator.item}]`; } return `[data-test=${locator.name}]:eq(${locator.index})`; }) .join(" "), options, ); }, );