diff --git a/manifest.json b/manifest.json index 5a77a949..86022555 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "name": "JDN — Page Object Generator", "description": "JDN – helps Test Automation Engineer to create Page Objects in the test automation framework and speed up test development", "devtools_page": "index.html", - "version": "3.15.23", + "version": "3.15.24", "icons": { "128": "icon128.png" }, diff --git a/package-lock.json b/package-lock.json index f8dbfd6c..029e14f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "jdn-ai-chrome-extension", - "version": "3.15.23", + "version": "3.15.24", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 337536fa..9b6d994f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jdn-ai-chrome-extension", - "version": "3.15.23", + "version": "3.15.24", "description": "jdn-ai chrome extension", "scripts": { "start": "webpack --watch --env devenv", diff --git a/src/__tests__/locators/utils/escapeLocatorString.test.ts b/src/__tests__/locators/utils/escapeLocatorString.test.ts new file mode 100644 index 00000000..a3d72380 --- /dev/null +++ b/src/__tests__/locators/utils/escapeLocatorString.test.ts @@ -0,0 +1,64 @@ +import { escapeLocatorString } from '../../../features/locators/utils/escapeLocatorString'; + +describe('escapeLocatorString', () => { + describe('should properly escape, when received', () => { + it('strings with double quotes', () => { + expect(escapeLocatorString('He said "Hello"')).toBe('He said \\"Hello\\"'); + }); + + it('strings with single quotes', () => { + expect(escapeLocatorString("It's a test")).toBe("It\\'s a test"); + }); + + it('strings with backslashes', () => { + expect(escapeLocatorString('Path\\to\\file')).toBe('Path\\\\to\\\\file'); + }); + + it('strings with mixed special characters', () => { + expect(escapeLocatorString('He said "It\'s alright"')).toBe('He said \\"It\\\'s alright\\"'); + }); + + it('JSON strings', () => { + const input = '{"category":"Header","action":"go to dashboard","label":"icon:logo"}'; + const expected = '{\\"category\\":\\"Header\\",\\"action\\":\\"go to dashboard\\",\\"label\\":\\"icon:logo\\"}'; + expect(escapeLocatorString(input)).toBe(expected); + }); + }); + + describe("shouldn't change", () => { + it('string without special characters', () => { + const normalString = 'Just a normal string'; + expect(escapeLocatorString(normalString)).toBe(normalString); + }); + + it('empty strings', () => { + expect(escapeLocatorString('')).toBe(''); + }); + + it('URL strings', () => { + const UrlString = '/orgs/jdi-testing/hovercard'; + expect(escapeLocatorString(UrlString)).toBe(UrlString); + }); + }); + + // tests for invalid data types: + describe('should throw an error or handle, when received', () => { + it('objects', () => { + const obj = { key: 'value' }; + expect(() => escapeLocatorString(obj as any)).toThrow(); + }); + + it('arrays', () => { + const arr = ['text1', 'text2']; + expect(() => escapeLocatorString(arr as any)).toThrow(); + }); + + it('null', () => { + expect(() => escapeLocatorString(null as any)).toThrow(); + }); + + it('undefined', () => { + expect(() => escapeLocatorString(undefined as any)).toThrow(); + }); + }); +}); diff --git a/src/features/locators/utils/escapeLocatorString.ts b/src/features/locators/utils/escapeLocatorString.ts new file mode 100644 index 00000000..69a6957d --- /dev/null +++ b/src/features/locators/utils/escapeLocatorString.ts @@ -0,0 +1,3 @@ +export const escapeLocatorString = (selector: string): string => { + return selector.replace(/(["'\\])/g, '\\$1'); +}; diff --git a/src/features/locators/utils/utils.ts b/src/features/locators/utils/utils.ts index 5732c8f4..489348e9 100644 --- a/src/features/locators/utils/utils.ts +++ b/src/features/locators/utils/utils.ts @@ -28,6 +28,7 @@ import { import { FormInstance } from 'rc-field-form/lib/interface'; import { FormValues } from '../components/LocatorEditDialog'; import { startsWithDigit } from '../../../app/utils/startsWithDigit'; +import { escapeLocatorString } from './escapeLocatorString'; export const isValidJavaVariable = (value: string) => /^[a-zA-Z_$]([a-zA-Z0-9_])*$/.test(value); @@ -43,10 +44,11 @@ export const evaluateStandardLocator = ( ) => sendMessage.evaluateStandardLocator({ selector, locatorType, element_id, originJdnHash }); const prepareLocatorStringForEvaluation = (type: LocatorType, string: string): string => { - if (type === LocatorType.id) return `#${string}`; - if (type === LocatorType.className) return `.${string}`; - if (type === LocatorType.name) return `[name="${string}"]`; - return string; + const escapeString = escapeLocatorString(string); + if (type === LocatorType.id) return `#${escapeString}`; + if (type === LocatorType.className) return `.${escapeString}`; + if (type === LocatorType.name) return `[name="${escapeString}"]`; + return escapeString; }; export const evaluateLocator = async (