diff --git a/src/features/locators/locators.slice.ts b/src/features/locators/locators.slice.ts index c758ed3f..b3ec6376 100644 --- a/src/features/locators/locators.slice.ts +++ b/src/features/locators/locators.slice.ts @@ -4,6 +4,7 @@ import { ElementClass, ElementLibrary } from "./types/generationClasses.types"; import { locatorsAdapter, simpleSelectLocatorById, + simpleSelectLocatorByJdnHash, simpleSelectLocatorsByPageObject, } from "./selectors/locators.selectors"; import { createLocatorsReducer } from "./reducers/createLocators.thunk"; @@ -20,6 +21,8 @@ import { LocatorTaskStatus, Locator, LocatorCalculationPriority, + JDNHash, + LocatorValue, } from "./types/locator.types"; import { checkLocatorsValidityReducer } from "./reducers/checkLocatorValidity.thunk"; import { LocatorType } from "../../common/types/common"; @@ -27,6 +30,7 @@ import { addCustomLocatorReducer } from "./reducers/addCustomLocator.thunk"; import { changeLocatorElementReducer } from "./reducers/changeLocatorElement.thunk"; import { DEFAULT_ERROR, NETWORK_ERROR } from "./utils/constants"; import { runLocatorsGenerationReducer } from "./reducers/runLocatorsGeneration.thunk"; +import { PageObject } from "../pageObjects/types/pageObjectSlice.types"; const initialState: LocatorsState = { generationStatus: LocatorsGenerationStatus.noStatus, @@ -79,7 +83,7 @@ const locatorsSlice = createSlice({ { payload }: PayloadAction; fromScript: boolean }> ) { const locators = Array.isArray(payload) ? payload : payload.locators; - locatorsAdapter.upsertMany(state, locators.map((_locator) => ({ ..._locator, active: true })) as Locator[]); + locatorsAdapter.upsertMany(state, locators.map(({ element_id }) => ({ element_id, active: true })) as Locator[]); }, elementGroupUnsetActive( state, @@ -199,8 +203,28 @@ const locatorsSlice = createSlice({ }); locatorsAdapter.upsertMany(state, newValue as Locator[]); }, - updateLocatorGroup(state, { payload }: PayloadAction) { - locatorsAdapter.upsertMany(state, payload); + updateLocatorGroup( + state, + { + payload, + }: PayloadAction<{ + locators: { element_id?: ElementId; jdnHash?: JDNHash; locator: Partial }[]; + pageObject: PageObject; + }> + ) { + const { locators, pageObject } = payload; + const newValue = locators.map(({ element_id, jdnHash, locator }) => { + const existingLocator = element_id + ? simpleSelectLocatorById(state, element_id) + : simpleSelectLocatorByJdnHash(state, jdnHash!, pageObject); + return ( + existingLocator && { + element_id: existingLocator.element_id, + locator: { ...existingLocator.locator, ...locator }, + } + ); + }); + locatorsAdapter.upsertMany(state, newValue as Locator[]); }, }, extraReducers: (builder) => { diff --git a/src/features/locators/reducers/runLocatorsGeneration.thunk.ts b/src/features/locators/reducers/runLocatorsGeneration.thunk.ts index efb12c3d..ac4d99f7 100644 --- a/src/features/locators/reducers/runLocatorsGeneration.thunk.ts +++ b/src/features/locators/reducers/runLocatorsGeneration.thunk.ts @@ -4,7 +4,8 @@ import { runXpathGeneration } from "../utils/runXpathGeneration"; import { MaxGenerationTime } from "../../../app/types/mainSlice.types"; import { RootState } from "../../../app/store/store"; import { runCssSelectorGeneration } from "../utils/runCssSelectorGeneration"; -import { locatorsAdapter } from "../selectors/locators.selectors"; +import { updateLocatorGroup } from "../locators.slice"; +import { selectCurrentPageObject } from "../../pageObjects/selectors/pageObjects.selectors"; interface Meta { locators: Locator[]; @@ -35,10 +36,39 @@ export const runLocatorsGeneration = createAsyncThunk( : null, ], ...[toGenerateCss.length ? runCssSelectorGeneration(toGenerateCss) : null], - Promise.resolve(toGenerateXpaths), - Promise.resolve(toGenerateCss), ]); + const setPendingXpaths = toGenerateXpaths + .filter((locator) => locator.locator && locator.locator.taskStatus !== LocatorTaskStatus.PENDING) + .map(({ element_id }) => ({ + element_id, + locator: { xPathStatus: LocatorTaskStatus.PENDING }, + })); + + const setPendingCss = toGenerateCss + .filter((locator) => locator.locator && locator.locator.taskStatus !== LocatorTaskStatus.PENDING) + .map(({ element_id }) => ({ + element_id, + locator: { cssSelectorStatus: LocatorTaskStatus.PENDING }, + })); + + const state = thunkAPI.getState() as RootState; + if (setPendingXpaths) + thunkAPI.dispatch( + updateLocatorGroup({ + locators: setPendingXpaths, + pageObject: selectCurrentPageObject(state)!, + }) + ); + + if (setPendingCss) + thunkAPI.dispatch( + updateLocatorGroup({ + locators: setPendingCss, + pageObject: selectCurrentPageObject(state)!, + }) + ); + return generations; } ); @@ -50,29 +80,7 @@ export const runLocatorsGenerationReducer = (builder: ActionReducerMapBuilder { state.generationStatus = LocatorsGenerationStatus.started; - const [_startXpaths, _startCss, toGenerateXpaths, toGenerateCss] = payload as [ - string | null, - string | null, - Locator[], - Locator[] - ]; - - const setPendingXpaths = toGenerateXpaths - .filter((locator) => locator.locator && locator.locator.taskStatus !== LocatorTaskStatus.PENDING) - .map(({ element_id, locator: { taskStatus: _, ...rest } }) => ({ - element_id, - locator: { ...rest, xPathStatus: LocatorTaskStatus.PENDING }, - })); - - const setPendingCss = toGenerateCss - .filter((locator) => locator.locator && locator.locator.taskStatus !== LocatorTaskStatus.PENDING) - .map(({ element_id, locator: { taskStatus: _, ...rest } }) => ({ - element_id, - locator: { ...rest, cssSelectorStatus: LocatorTaskStatus.PENDING }, - })); - - // @ts-ignore - locatorsAdapter.upsertMany(state, [...setPendingXpaths, ...setPendingCss] as Locator[]); + const [_startXpaths, _startCss] = payload as [string | null, string | null]; }) .addCase(runLocatorsGeneration.rejected, (state, { error }) => { throw new Error(error.stack); diff --git a/src/features/locators/selectors/locators.selectors.ts b/src/features/locators/selectors/locators.selectors.ts index c356ba58..dc644e72 100644 --- a/src/features/locators/selectors/locators.selectors.ts +++ b/src/features/locators/selectors/locators.selectors.ts @@ -1,6 +1,6 @@ import { createDraftSafeSelector, createEntityAdapter, createSelector, EntityState } from "@reduxjs/toolkit"; import { RootState } from "../../../app/store/store"; -import { PageObjectId } from "../../pageObjects/types/pageObjectSlice.types"; +import { PageObject, PageObjectId } from "../../pageObjects/types/pageObjectSlice.types"; import { ElementId, Locator } from "../types/locator.types"; import { getLocator } from "../utils/locatorOutput"; import { selectCurrentPageObject } from "../../pageObjects/selectors/pageObjects.selectors"; @@ -77,6 +77,14 @@ export const areChildrenChecked = createSelector( locator.children?.every((childId) => locators.some((loc) => loc.element_id === childId && loc.generate)) ); +export const selectLocatorByJdnHash = createSelector( + (state: RootState, jdnHash: string) => selectLocators(state).filter((loc) => loc.jdnHash === jdnHash), + (state: RootState) => selectCurrentPageObject(state)?.locators, + (locators, pageObjLocators) => { + return locators.find(({ element_id }) => pageObjLocators?.includes(element_id)); + } +); + /* these selectors are for using inside reducers */ export const { selectAll: simpleSelectLocators, selectById: simpleSelectLocatorById } = locatorsAdapter.getSelectors(); @@ -91,11 +99,10 @@ export const simpleSelectLocatorsByPageObject = createDraftSafeSelector( (locators: Locator[], pageObj: PageObjectId) => locators.filter((_loc) => _loc.pageObj === pageObj) ); - // move to loc - export const selectLocatorByJdnHash = createSelector( - (state: RootState, jdnHash: string) => selectLocators(state).filter((loc) => loc.jdnHash === jdnHash), - (state: RootState) => selectCurrentPageObject(state)?.locators, - (locators, pageObjLocators) => { - return locators.find(({ element_id }) => pageObjLocators?.includes(element_id)); - } - ); +export const simpleSelectLocatorByJdnHash = createDraftSafeSelector( + (state: EntityState, jdnHash: string) => simpleSelectLocators(state).filter((loc) => loc.jdnHash === jdnHash), + (_state: EntityState, _: string, pageObject: PageObject) => pageObject.locators, + (locators, pageObjLocators) => { + return locators.find(({ element_id }) => pageObjLocators?.includes(element_id)); + } +); \ No newline at end of file diff --git a/src/pageServices/scriptMessageHandler.ts b/src/pageServices/scriptMessageHandler.ts index 8b683495..47b78f02 100644 --- a/src/pageServices/scriptMessageHandler.ts +++ b/src/pageServices/scriptMessageHandler.ts @@ -18,9 +18,10 @@ import { showOverlay } from "./pageDataHandlers"; import { rerunGeneration } from "../features/locators/reducers/rerunGeneration.thunk"; import { stopGenerationGroup } from "../features/locators/reducers/stopGenerationGroup.thunk"; import { copyLocator } from "../features/locators/utils/utils"; -import { selectLocatorById, selectLocatorByJdnHash } from "../features/locators/selectors/locators.selectors"; +import { selectLocatorByJdnHash } from "../features/locators/selectors/locators.selectors"; import { ScriptMsg } from "./scriptMsg.constants"; import { selectPresentActiveLocators } from "../features/locators/selectors/locatorsByPO.selectors"; +import { selectCurrentPageObject } from "../features/pageObjects/selectors/pageObjects.selectors"; export type ScriptMessagePayload = { message: keyof Actions; param: Record }; @@ -64,14 +65,14 @@ export const updateMessageHandler = ( }, [ScriptMsg.RemoveElement]: (payload) => dispatch(toggleDeletedGroup(payload)), [ScriptMsg.ResponseCssSelectors]: (payload) => { - const res = payload.map((element: Locator) => { - const { taskStatus: _, ...rest } = selectLocatorById(state, element.element_id)!.locator; + const locators = payload.map(({ element_id, locator }: Locator) => { return { - ...element, - locator: { ...rest, ...element.locator, cssSelectorStatus: LocatorTaskStatus.SUCCESS }, + element_id, + locator: { ...locator, cssSelectorStatus: LocatorTaskStatus.SUCCESS }, }; }); - dispatch(updateLocatorGroup(res)); + const pageObject = selectCurrentPageObject(state)!; + dispatch(updateLocatorGroup({ locators, pageObject })); }, [ScriptMsg.RestoreElement]: (payload) => dispatch(toggleDeletedGroup(payload)), [ScriptMsg.OpenEditLocator]: () => { diff --git a/src/pageServices/scriptNotifier.ts b/src/pageServices/scriptNotifier.ts index b5a47e99..65a74b93 100644 --- a/src/pageServices/scriptNotifier.ts +++ b/src/pageServices/scriptNotifier.ts @@ -1,6 +1,6 @@ import { Middleware } from "@reduxjs/toolkit"; import { compact, isNil, size } from "lodash"; -import { selectLocatorById } from "../features/locators/selectors/locators.selectors"; +import { selectLocatorById, selectLocatorByJdnHash } from "../features/locators/selectors/locators.selectors"; import { Locator, LocatorTaskStatus, LocatorValidationWarnings } from "../features/locators/types/locator.types"; import { sendMessage } from "./connector"; import { selectCurrentPage } from "../app/main.selectors"; @@ -140,8 +140,8 @@ const notify = (state: RootState, action: any, prevState: RootState) => { }); break; case "locators/updateLocatorGroup": - payload.forEach((element: Locator) => { - const locator = selectLocatorById(state, element.element_id); + payload.locators.forEach(({ element_id, jdnHash }: Locator) => { + const locator = element_id ? selectLocatorById(state, element_id) : selectLocatorByJdnHash(state, jdnHash!); locator && sendMessage.changeStatus(locator); }); break; diff --git a/src/services/webSocketMessageHandler.ts b/src/services/webSocketMessageHandler.ts index 268def4c..b8dc31e5 100644 --- a/src/services/webSocketMessageHandler.ts +++ b/src/services/webSocketMessageHandler.ts @@ -7,6 +7,7 @@ import { locatorGenerationController } from "../features/locators/utils/locatorG import { sendMessage } from "../pageServices/connector"; import { webSocketController } from "./webSocketController"; import { selectInProgressByPageObj } from "../features/locators/selectors/locatorsFiltered.selectors"; +import { selectCurrentPageObject } from "../features/pageObjects/selectors/pageObjects.selectors"; const reScheduledTasks = new Set(); @@ -44,27 +45,25 @@ export const updateSocketMessageHandler = (dispatch: any, state: any) => { } if (status === LocatorTaskStatus.REVOKED || status === LocatorTaskStatus.FAILURE) { - dispatch(updateLocatorGroup([{ ...element, locator: { ...element.locator, ...{ xPathStatus: status } } }])); + const pageObject = selectCurrentPageObject(state)!; + dispatch(updateLocatorGroup({ locators: [{ jdnHash, locator: { xPathStatus: status } }], pageObject })); } break; } case "result_ready": { - const onStatusChange = (payloads: any[]) => { - const locators = payloads.map((_payload) => { - const { element } = _payload; - const { result: xPath } = _payload.payload; - const { taskStatus: _, ...rest } = element.locator; + const onStatusChange = (payload: any[]) => { + const locators = payload.map((_payload) => { + const { id, result: xPath } = _payload; return { - ...element, - locator: { ...rest, ...{ xPath, xPathStatus: LocatorTaskStatus.SUCCESS } }, + jdnHash: id, + locator: { xPath, xPathStatus: LocatorTaskStatus.SUCCESS }, }; }); - dispatch(updateLocatorGroup(locators)); + const pageObject = selectCurrentPageObject(state)!; + dispatch(updateLocatorGroup({ locators, pageObject })); }; - const { id: jdnHash } = payload; - const element = selectLocatorByJdnHash(state, jdnHash); - if (element) debouncer.accumulateAndDebounce(onStatusChange)([{ payload, element }]); + debouncer.accumulateAndDebounce(onStatusChange)([payload]); break; } }