From 13b09e1cfdc226233737b930602f607cd584d175 Mon Sep 17 00:00:00 2001 From: Mishnya Date: Mon, 13 Nov 2023 11:33:59 +0300 Subject: [PATCH] feat: add id converter for getXpath --- src/components/utils/__tests__/xpath.test.tsx | 46 +++++++++++++++++++ src/components/utils/xpath.ts | 11 ++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/components/utils/__tests__/xpath.test.tsx b/src/components/utils/__tests__/xpath.test.tsx index 4eeb386967..d17b2656f0 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 2bc5868436..4b8ff4c158 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, };