diff --git a/src/components/utils/__tests__/xpath.test.tsx b/src/components/utils/__tests__/xpath.test.tsx index 4eeb38696..d17b2656f 100644 --- a/src/components/utils/__tests__/xpath.test.tsx +++ b/src/components/utils/__tests__/xpath.test.tsx @@ -313,5 +313,51 @@ describe('getXpath', () => { expect(xpath).toBe(rootBuilder.append({className: 'class__div'}).xpath); expect(hash).toMatchInlineSnapshot(`"bf5138ce0f335973b588b4c3029e1335"`); }); + + it('should remove id if it was converted to undefined', () => { + const onClick = jest.fn(); + render( +
+
+
+ {clickText} +
+
+
, + ); + screen.getByText(clickText).click(); + + const {xpath, hash} = getXpath(onClick.mock.calls[0][0], { + idConverter: (id) => (id.startsWith('remove') ? undefined : id), + }); + expect(xpath).toBe( + rootBuilder.append().append({id: 'keep-this'}).append({className: 'target class-3'}) + .xpath, + ); + expect(hash).toMatchInlineSnapshot(`"21df5cf9017ae106f30a9a6608a9cb4a"`); + }); + + it('should convert some ids', () => { + const onClick = jest.fn(); + render( +
+
+
+ {clickText} +
+
+
, + ); + screen.getByText(clickText).click(); + + const {xpath, hash} = getXpath(onClick.mock.calls[0][0], { + idConverter: (id) => id.replace('convert', 'keep'), + }); + expect(xpath).toBe( + rootBuilder.append({id: 'keep-too'}).append({id: 'keep-this'}).append({id: 'keep'}) + .xpath, + ); + expect(hash).toMatchInlineSnapshot(`"2ac575742aa22271a17b4e1efb375330"`); + }); }); }); diff --git a/src/components/utils/xpath.ts b/src/components/utils/xpath.ts index 2bc586843..4b8ff4c15 100644 --- a/src/components/utils/xpath.ts +++ b/src/components/utils/xpath.ts @@ -12,9 +12,13 @@ export type XpathClassConverter = ( strClass: string, ) => ElementClass | undefined; +export type XpathIdConverter = (id: string) => string | undefined; + export interface XpathOptions { /** Function for converting and filtering classes */ classConverter?: XpathClassConverter; + /** Function for converting and filtering ids */ + idConverter?: XpathIdConverter; /** Flag for managing replaces from tag[@class='...'] to tag[@id='...'] if id is exist */ withoutId?: boolean; } @@ -39,8 +43,10 @@ function getXpathByNode(node: Node | null, options: InternalXpathOptions): strin const tag = node.tagName.toLowerCase(); let token = `/${tag}`; - if (node.id && !options.withoutId) { - token += `[@id='${node.id}']`; + + const convertedId = node.id && !options.withoutId ? options.idConverter(node.id) : undefined; + if (convertedId) { + token += `[@id='${convertedId}']`; } else { const classes: string[] = []; node.classList.forEach((className) => { @@ -59,6 +65,7 @@ function getXpathByNode(node: Node | null, options: InternalXpathOptions): strin const defaultXpathOptions: InternalXpathOptions = { classConverter: (arg) => arg, + idConverter: (arg) => arg, withoutId: false, };