From f39a54b067859e9f5430135ebc9157256a9a34b5 Mon Sep 17 00:00:00 2001 From: Anna Iustus Date: Fri, 26 Jul 2024 15:35:19 +0200 Subject: [PATCH 1/7] fix: create dropdown options for locator types --- src/common/components/DialogWithForm.tsx | 5 +- src/features/locators/Locator.tsx | 3 - .../reducers/changeLocatorElement.thunk.ts | 2 +- .../utils/createLocatorTypeOptions.tsx | 58 +++++++++++++------ .../locators/utils/locatorValidationRules.ts | 1 + 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/common/components/DialogWithForm.tsx b/src/common/components/DialogWithForm.tsx index 7d37a660..5d55f433 100644 --- a/src/common/components/DialogWithForm.tsx +++ b/src/common/components/DialogWithForm.tsx @@ -21,6 +21,7 @@ interface OnboardingRefProps { onNextClickHandler: () => void; isOkButtonDisabled: boolean; } + interface DialogFormProps { modalProps: JDNModalProps; children?: ReactNode; @@ -79,11 +80,11 @@ export const DialogWithForm: React.FC = ({ modalProps, formProp onOk={onOk} open={open} okButtonProps={okButtonProps} - {...{ ...restModal }} + {...restModal} > {open ? (
}> -
+ {children}
diff --git a/src/features/locators/Locator.tsx b/src/features/locators/Locator.tsx index 5d26f270..a1b9cb3f 100644 --- a/src/features/locators/Locator.tsx +++ b/src/features/locators/Locator.tsx @@ -1,5 +1,3 @@ -// ToDo fix naming according to naming-convention -/* eslint-disable @typescript-eslint/naming-convention */ import React, { FC, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { Button, Checkbox } from 'antd'; import { DotsThree } from '@phosphor-icons/react'; @@ -52,7 +50,6 @@ interface Props { export const Locator: FC = ({ element, currentPage, searchState, depth, searchString, index }) => { const dispatch = useDispatch(); - const [isEditModalOpen, setIsEditModalOpen] = useState(false); const { diff --git a/src/features/locators/reducers/changeLocatorElement.thunk.ts b/src/features/locators/reducers/changeLocatorElement.thunk.ts index eedbfb9b..934d5521 100644 --- a/src/features/locators/reducers/changeLocatorElement.thunk.ts +++ b/src/features/locators/reducers/changeLocatorElement.thunk.ts @@ -60,7 +60,7 @@ export const changeLocatorElement = createAsyncThunk( elemText: foundElementText || '', jdnHash: foundHash, }; - // почему здесь так, почему не отправляется на бэк WS message? для генерации xPath (и cssSelector) + if (isCSSLocator) { fullXpath = await getElementFullXpath(foundHash); newValue.locatorValue.cssSelector = locatorValue; diff --git a/src/features/locators/utils/createLocatorTypeOptions.tsx b/src/features/locators/utils/createLocatorTypeOptions.tsx index fc7b51f8..87283b41 100644 --- a/src/features/locators/utils/createLocatorTypeOptions.tsx +++ b/src/features/locators/utils/createLocatorTypeOptions.tsx @@ -24,7 +24,7 @@ export interface ILocatorTypeOptions { options?: IOptionsWithLabel[]; } -const generateOptionsWithLabel = (attributes: ElementAttributes): IOptionsWithLabel[] => { +const generateOptionsWithLabel = (attributes: ElementAttributes, isVividusFramework: boolean): IOptionsWithLabel[] => { const generateLabel = (locatorType: string, attribute: string | null) => { if (attribute === null || attribute === '') { return ( @@ -37,21 +37,43 @@ const generateOptionsWithLabel = (attributes: ElementAttributes): IOptionsWithLa return <>{locatorType}; }; - return Object.keys(attributes).map((key) => { - let locatorType = key; + const options: IOptionsWithLabel[] = []; + + for (const dataKey of Object.keys(attributes)) { + let locatorType = dataKey; if (locatorType === 'cssSelector') locatorType = 'CSS Selector'; - const option: IOptionsWithLabel = { - label: generateLabel(locatorType, attributes[key as keyof ElementAttributes] as string), - value: locatorType, - desc: attributes[key as keyof ElementAttributes] as string, - }; - - if (attributes[key as keyof ElementAttributes] === null) { - option.disabled = true; + + if (isVividusFramework && dataKey.startsWith('data-') && attributes[dataKey as keyof ElementAttributes]) { + const dataValue: string = attributes[dataKey as keyof ElementAttributes] as string; + + if (dataValue !== null && dataValue !== '') { + options.push({ + label: generateLabel('CSS Selector', dataValue), + value: `cssSelector-data-${dataKey}`, + desc: `*[${dataKey}="${dataValue}"]`, + }); + options.push({ + label: generateLabel('xPath', dataValue), + value: `xPath-data-${dataKey}`, + desc: `//*[@${dataKey}='${dataValue}']`, + }); + } + } else { + const option: IOptionsWithLabel = { + label: generateLabel(locatorType, attributes[dataKey as keyof ElementAttributes] as string), + value: locatorType, + desc: attributes[dataKey as keyof ElementAttributes] as string, + }; + + if (attributes[dataKey as keyof ElementAttributes] === null) { + option.disabled = true; + } + + options.push(option); } + } - return option; - }); + return options; }; const addRestAttributes = ( @@ -65,7 +87,6 @@ const addRestAttributes = ( const updatedUniqueAttributes: ExtendedElementAttributes = { ...uniqueAttributes, xPath, cssSelector }; const updatedNonUniqueAttributes: ElementAttributes = nonUniqueAttributes; - // Add noData fields: Object.entries(allLocatorAttributes).forEach(([key, value]) => { if (!updatedUniqueAttributes.hasOwnProperty(key) && !updatedNonUniqueAttributes.hasOwnProperty(key)) { updatedNonUniqueAttributes[key as keyof ElementAttributes] = value; @@ -79,13 +100,14 @@ const getLocatorTypeOptions = ( attributes: ElementAttributes[], cssSelector: string | null, xPath: string | null, + isVividusFramework: boolean, ): ILocatorTypeOptions[] => { const [updatedUniqueAttributes, updatedNonUniqueAttributes] = addRestAttributes(attributes, cssSelector, xPath); - const uniqueOptions = generateOptionsWithLabel(updatedUniqueAttributes) + const uniqueOptions = generateOptionsWithLabel(updatedUniqueAttributes, isVividusFramework) .slice() .sort((a, b) => a.value.localeCompare(b.value)); - const nonUniqueOptions = generateOptionsWithLabel(updatedNonUniqueAttributes) + const nonUniqueOptions = generateOptionsWithLabel(updatedNonUniqueAttributes, isVividusFramework) .slice() .sort((a, b) => a.value.localeCompare(b.value)); @@ -155,14 +177,12 @@ const splitUniqueAndNonUniqueAttributes = async (attributes: ElementAttributes): export const createLocatorTypeOptions = async (locatorValue: LocatorValue, isVividusFramework: boolean) => { const attributes: ElementAttributes = {}; Object.assign(attributes, locatorValue.attributes); - if (isVividusFramework) { - delete attributes.dataAttributes; - } const optionsData = await splitUniqueAndNonUniqueAttributes(attributes); return getLocatorTypeOptions( optionsData, locatorValue.cssSelector ?? locatorValue.originalCssSelector ?? null, locatorValue.xPath, + isVividusFramework, ); }; diff --git a/src/features/locators/utils/locatorValidationRules.ts b/src/features/locators/utils/locatorValidationRules.ts index 59da7ce0..133295a4 100644 --- a/src/features/locators/utils/locatorValidationRules.ts +++ b/src/features/locators/utils/locatorValidationRules.ts @@ -34,6 +34,7 @@ export const createLocatorValidationRules = ( setValidationMessage(validationMessage as LocatorValidationErrorType); return await Promise.resolve(); } catch (err) { + console.error('another validation error'); setValidationMessage(err.message as LocatorValidationErrorType); setValidationErrorOptions(err.options); return Promise.reject(err); From 99f1f166b074b2ca7008f0410dfe1481fafc8366 Mon Sep 17 00:00:00 2001 From: Anna Iustus Date: Tue, 30 Jul 2024 22:44:54 +0200 Subject: [PATCH 2/7] fix: evaluation and full flow for xPath (data attributes for Vividus); fix validation and textarea writing for CSS --- .../locators/components/LocatorEditDialog.tsx | 62 ++++++++++------ .../locators/components/LocatorsTree.tsx | 14 +--- src/features/locators/locators.slice.ts | 3 +- src/features/locators/utils/locatorOutput.tsx | 33 +++++++-- src/features/locators/utils/utils.ts | 71 ++++++++++++++++++- src/pageServices/contentScripts/utils.ts | 6 +- 6 files changed, 144 insertions(+), 45 deletions(-) diff --git a/src/features/locators/components/LocatorEditDialog.tsx b/src/features/locators/components/LocatorEditDialog.tsx index 0b8a3860..665ab9be 100644 --- a/src/features/locators/components/LocatorEditDialog.tsx +++ b/src/features/locators/components/LocatorEditDialog.tsx @@ -80,6 +80,7 @@ export const LocatorEditDialog: React.FC = ({ const [isEditedName, setIsEditedName] = useState(isCustomName); const [form] = Form.useForm(); + const isCurrentFrameworkVividus = pageObjectFramework === FrameworkType.Vividus; // ToDo rewrite all related logic and tests for defaultLocatorType: string (because it's string) const defaultLocatorType: LocatorType = locatorType || pageObjectLocatorType || LocatorType.xPath; @@ -105,6 +106,25 @@ export const LocatorEditDialog: React.FC = ({ }; const notShownElementIds = useSelector(selectNotShownElementIds); + + const [textareaValue, setTextareaValue] = useState(''); + + const handleTypeChangeBySelect = (value: string, option: { desc: React.SetStateAction }) => { + console.log('handleTypeChangeBySelect ', option.desc); + setTextareaValue(option.desc); + form.setFieldValue('locator', option.desc); + + if (isEditedName) return; + + const newName = createNewName( + { elementId, isCustomName, type, name, elemId, elemName, elemText } as ILocator, + value, + library, + locators, + ); + form.setFieldValue('name', newName); + }; + const getLocatorValidationRules: () => Rule[] = () => createLocatorValidationRules( isCreatingForm, @@ -116,19 +136,8 @@ export const LocatorEditDialog: React.FC = ({ elementId, notShownElementIds, ); - const [locatorValidationRules, setLocatorValidationRules] = useState(getLocatorValidationRules()); - const handleTypeChange = (value: string) => { - if (isEditedName) return; - - const newName = createNewName( - { elementId, isCustomName, type, name, elemId, elemName, elemText } as ILocator, - value, - library, - locators, - ); - form.setFieldValue('name', newName); - }; + const [locatorValidationRules, setLocatorValidationRules] = useState(getLocatorValidationRules()); const handleNameChange = () => { setIsEditedName(true); @@ -191,7 +200,7 @@ export const LocatorEditDialog: React.FC = ({ if ((!validationMessage.length && !jdnHash) || validationMessage === LocatorValidationWarnings.NewElement) { await dispatch(changeLocatorElement(updatedLocator)); } else { - dispatch(changeLocatorAttributes(updatedLocator)); + dispatch(changeLocatorAttributes({ ...updatedLocator, isCurrentFrameworkVividus })); } closeDialog(); @@ -223,12 +232,12 @@ export const LocatorEditDialog: React.FC = ({ ) : null; - const onLocatorTypeChange = async () => { + const onLocatorTypeChange = async (newLocatorType: LocatorType) => { setLocatorValidationRules(getLocatorValidationRules()); - const newLocatorType = form.getFieldValue('locatorType'); - const newLocator = form.getFieldValue('locator'); - if (newLocator !== '') { + const previousLocatorValue = form.getFieldValue('locator'); + + if (previousLocatorValue !== '') { const newLocatorValue = await getLocatorValueOnTypeSwitch( newLocatorType, validationMessage, @@ -243,7 +252,10 @@ export const LocatorEditDialog: React.FC = ({ const onFieldsChange = async (changedValues: FieldData[]) => { const isLocatorTypeChanged = changedValues.some((value) => value.name.toString().includes('locatorType')); - if (isLocatorTypeChanged) await onLocatorTypeChange(); + if (isLocatorTypeChanged) { + const newLocatorType = changedValues.find((value) => value.name.toString().includes('locatorType'))?.value; + await onLocatorTypeChange(newLocatorType); + } setIsOkButtonDisabled(computeIsOkButtonDisabled()); }; @@ -264,6 +276,7 @@ export const LocatorEditDialog: React.FC = ({ value: value, })); const [locatorTypeOptions, setLocatorTypeOptions] = useState([]); + useEffect(() => { if (!isCreatingForm) { const fetchLocatorTypeOptions = async () => { @@ -281,7 +294,8 @@ export const LocatorEditDialog: React.FC = ({ } }, [locatorValue, locators, elementId]); - const handleLocatorDropdownOnChange = async () => { + const handleLocatorDropdownOnChange = async (_: any, option: { desc: React.SetStateAction }) => { + setTextareaValue(option.desc); setValidationMessage(''); try { @@ -344,7 +358,7 @@ export const LocatorEditDialog: React.FC = ({ ]} >