Skip to content

Commit

Permalink
refactor: code cleanup and code style fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Iogsotot committed Aug 14, 2024
1 parent 6034d05 commit 9ce565b
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 113 deletions.
4 changes: 2 additions & 2 deletions src/features/filter/reducers/toggleClassFilter.thunk.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { filterAdapter, simpleSelectFilterById } from '../filter.selectors';
import { RootState } from '../../../app/store/store';
import { FilterKey, Filter, ClassFilterValue } from '../types/filter.types';
import { ClassFilterValue, Filter, FilterKey } from '../types/filter.types';
import { jdiClassFilterInit } from '../utils/filterSet';
import { PageObjectId } from '../../pageObjects/types/pageObjectSlice.types';
import { ElementClass, ElementLibrary } from '../../locators/types/generationClasses.types';
import { LocalStorageKey, setLocalStorage, getLocalStorage } from '../../../common/utils/localStorage';
import { getLocalStorage, LocalStorageKey, setLocalStorage } from '../../../common/utils/localStorage';

interface toggleClassFilterPayload {
pageObjectId: PageObjectId;
Expand Down
186 changes: 98 additions & 88 deletions src/features/locators/reducers/runLocatorsGeneration.thunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,106 +20,115 @@ interface Meta {
generateMissingLocator?: boolean;
}

/* Purpose of this thunk is to start locators generation.
It's used for initial locators generation, or can be called on demand for particular locator type
or with parameters.
*/
export const runLocatorsGeneration = createAsyncThunk(
'locators/runLocatorsGeneration',
async (meta: Meta, thunkAPI) => {
const state = thunkAPI.getState() as RootState;
try {
const state = thunkAPI.getState() as RootState;

const currentPageObjLibrary = selectCurrentPageObject(state)?.library;
const { locators, maxGenerationTime, generateXpath, generateCssSelector, generateMissingLocator } = meta;
const currentPageObjLibrary = selectCurrentPageObject(state)?.library;
const { locators, maxGenerationTime, generateXpath, generateCssSelector, generateMissingLocator } = meta;

let filter = selectClassFilterByPO(state);
if (currentPageObjLibrary && getLocalStorage(LocalStorageKey.Filter)) {
filter = getLocalStorage(LocalStorageKey.Filter)[currentPageObjLibrary];
}
let filter = selectClassFilterByPO(state);

const getXPathsForGeneration = (): ILocator[] => {
if (maxGenerationTime) {
return locators;
} else if (generateMissingLocator || generateXpath) {
return filterLocatorsByClassFilter(locators, filter).filter(
({ locatorValue }) =>
!locatorValue ||
!locatorValue.xPath ||
locatorValue.xPath === locatorValue.fullXpath ||
!locatorValue.fullXpath,
);
} else {
return [];
if (currentPageObjLibrary && getLocalStorage(LocalStorageKey.Filter)) {
const storedFilters = getLocalStorage(LocalStorageKey.Filter);
filter = storedFilters ? storedFilters[currentPageObjLibrary] || {} : {};
}
};

const toGenerateXPaths: ILocator[] = getXPathsForGeneration();
const getXPathsForGeneration = (): ILocator[] => {
if (maxGenerationTime) {
return locators;
} else if (generateMissingLocator || generateXpath) {
if (!filter || Object.keys(filter).length === 0) {
console.error('filter is empty or invalid:', filter);
return locators;
}
const res = filterLocatorsByClassFilter(locators, filter).filter(
({ locatorValue }) =>
!locatorValue ||
!locatorValue.xPath ||
locatorValue.xPath === locatorValue.fullXpath ||
!locatorValue.fullXpath,
);

const toGenerateCss =
generateMissingLocator || generateCssSelector
? filterLocatorsByClassFilter(locators, filter).filter(
({ locatorValue }) => !locatorValue || !locatorValue.cssSelector,
)
: [];
return res;
} else {
return locators;
}
};

const pageDocumentForRubula = selectPageDocumentForRobula(state);
if (pageDocumentForRubula === null) {
console.error(`can't run Xpath Generation: Page Document For Robula is null`);
return;
}
const toGenerateXPaths: ILocator[] = getXPathsForGeneration();

const generations = Promise.all([
...[
toGenerateXPaths.length || toGenerateCss.length
? runLocatorGeneration(
state,
[...toGenerateXPaths, ...toGenerateCss],
pageDocumentForRubula,
maxGenerationTime,
const toGenerateCss =
generateMissingLocator || generateCssSelector
? filterLocatorsByClassFilter(locators, filter).filter(
({ locatorValue }) => !locatorValue || !locatorValue.cssSelector,
)
: null,
],
]);

const XPathsSelectorsPending = toGenerateXPaths
.filter((locator) => {
const taskStatus = getTaskStatus(locator.locatorValue.xPathStatus, locator.locatorValue.cssSelectorStatus);
return locator.locatorValue && taskStatus !== LocatorTaskStatus.PENDING;
})
.map(({ elementId, jdnHash }) => ({
elementId,
locatorValue: { xPathStatus: LocatorTaskStatus.PENDING },
jdnHash,
}));

const cssSelectorsPending = toGenerateCss
.filter((locator) => {
const taskStatus = getTaskStatus(locator.locatorValue.xPathStatus, locator.locatorValue.cssSelectorStatus);
return locator.locatorValue && taskStatus !== LocatorTaskStatus.PENDING;
})
.map(({ elementId, jdnHash }) => ({
elementId,
locatorValue: { cssSelectorStatus: LocatorTaskStatus.PENDING },
jdnHash,
}));

if (XPathsSelectorsPending.length)
thunkAPI.dispatch(
updateLocatorGroup({
locators: XPathsSelectorsPending,
pageObject: selectCurrentPageObject(state)!,
}),
);

if (cssSelectorsPending.length)
thunkAPI.dispatch(
updateLocatorGroup({
locators: cssSelectorsPending,
pageObject: selectCurrentPageObject(state)!,
}),
);

return generations;
: [];

const pageDocumentForRubula = selectPageDocumentForRobula(state);
if (pageDocumentForRubula === null) {
console.error(`can't run Xpath Generation: Page Document For Robula is null`);
return;
}

const generations = await Promise.all([
...[
toGenerateXPaths.length || toGenerateCss.length
? runLocatorGeneration(
state,
[...toGenerateXPaths, ...toGenerateCss],
pageDocumentForRubula,
maxGenerationTime,
)
: null,
],
]);

const XPathsSelectorsPending = toGenerateXPaths
.filter((locator) => {
const taskStatus = getTaskStatus(locator.locatorValue.xPathStatus, locator.locatorValue.cssSelectorStatus);
return locator.locatorValue && taskStatus !== LocatorTaskStatus.PENDING;
})
.map(({ elementId, jdnHash }) => ({
elementId,
locatorValue: { xPathStatus: LocatorTaskStatus.PENDING },
jdnHash,
}));

const cssSelectorsPending = toGenerateCss
.filter((locator) => {
const taskStatus = getTaskStatus(locator.locatorValue.xPathStatus, locator.locatorValue.cssSelectorStatus);
return locator.locatorValue && taskStatus !== LocatorTaskStatus.PENDING;
})
.map(({ elementId, jdnHash }) => ({
elementId,
locatorValue: { cssSelectorStatus: LocatorTaskStatus.PENDING },
jdnHash,
}));

if (XPathsSelectorsPending.length)
thunkAPI.dispatch(
updateLocatorGroup({
locators: XPathsSelectorsPending,
pageObject: selectCurrentPageObject(state)!,
}),
);

if (cssSelectorsPending.length)
thunkAPI.dispatch(
updateLocatorGroup({
locators: cssSelectorsPending,
pageObject: selectCurrentPageObject(state)!,
}),
);

return generations;
} catch (error) {
console.error('Error in runLocatorsGeneration:', error);
throw error;
}
},
);

Expand All @@ -133,6 +142,7 @@ export const runLocatorsGenerationReducer = (builder: ActionReducerMapBuilder<Lo
const [_startXPaths, _startCss] = payload as [string | null, string | null];
})
.addCase(runLocatorsGeneration.rejected, (state, { error }) => {
console.error('runLocatorsGeneration was rejected:', error);
throw new Error(error.stack);
});
};
45 changes: 24 additions & 21 deletions src/features/locators/selectors/locatorsByPO.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,31 @@ export const selectPresentLocatorsByPO = createSelector(
(state: RootState, pageObjId?: PageObjectId) =>
isNil(pageObjId) ? selectCurrentPageObject(state) : selectPageObjById(state, pageObjId),
(locators, pageObject) => {
const locByPageObj = pageObject?.locators || [];
return locators
.filter((locator) => locByPageObj.includes(locator.elementId))
.map((locator) => {
const annotationType = locator.annotationType || pageObject?.annotationType;
const locatorType = locator.locatorType || pageObject?.locatorType || LocatorType.xPath;
// ToDo: isDefaultLocatorType ???
const isDefaultLocatorType = () => !locator.locatorType && pageObject?.locatorType === LocatorType.cssSelector;
if (!pageObject) return [];

const res: ILocator = {
...locator,
...(annotationType && { annotationType }),
...(locatorType && { locatorType }),
...(isDefaultLocatorType() && {
locatorValue: {
...locator.locatorValue,
output: getLocator(locator.locatorValue, pageObject?.locatorType),
},
}),
};
return res;
});
const locByPageObj = pageObject.locators || [];
const filteredLocators = locators.filter((locator) => locByPageObj.includes(locator.elementId));
const mappedLocators = filteredLocators.map((locator) => {
const annotationType = locator.annotationType || pageObject.annotationType;
const locatorType = locator.locatorType || pageObject.locatorType || LocatorType.xPath;

const isDefaultLocatorType = () => !locator.locatorType && pageObject.locatorType === LocatorType.cssSelector;

const res: ILocator = {
...locator,
...(annotationType && { annotationType }),
...(locatorType && { locatorType }),
...(isDefaultLocatorType() && {
locatorValue: {
...locator.locatorValue,
output: getLocator(locator.locatorValue, pageObject.locatorType),
},
}),
};
return res;
});

return mappedLocators;
},
);

Expand Down
12 changes: 10 additions & 2 deletions src/features/locators/utils/filterLocators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import { ClassFilterValue } from '../../filter/types/filter.types';
import { areAllValuesFalse } from './helpers';

export const filterLocatorsByClassFilter = (locators: ILocator[], filter: ClassFilterValue) => {
if (!filter || areAllValuesFalse(filter)) return locators;
if (!filter || areAllValuesFalse(filter)) {
return locators;
}

const filteredLocators = locators?.filter((locator) => {
const filterValue = filter;
return Object.hasOwn(filterValue, locator.type) ? get(filterValue, locator.type) : true;
const hasFilterValue = Object.hasOwn(filterValue, locator.type);
const filterResult = get(filterValue, locator.type);
return hasFilterValue ? filterResult : true;
});

if (filteredLocators === undefined) {
console.error('filteredLocators is undefined');
}

return filteredLocators;
};

0 comments on commit 9ce565b

Please sign in to comment.