@onehat/ui 0.3.287 → 0.3.288
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Components/Buttons/ReloadButton.js +37 -0
- package/src/Components/Buttons/ReloadPageButton.js +2 -26
- package/src/Components/Buttons/ReloadTreeButton.js +6 -0
- package/src/Components/Grid/Grid.js +7 -7
- package/src/Components/Hoc/withEditor.js +10 -5
- package/src/Components/Hoc/withSideEditor.js +1 -1
- package/src/Components/Tree/Tree.js +42 -14
- package/src/Components/Tree/TreeNode.js +3 -1
- package/src/Functions/Cypress/button_functions.js +4 -1
- package/src/Functions/Cypress/crud_functions.js +283 -60
- package/src/Functions/Cypress/tree_functions.js +254 -0
package/package.json
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Icon,
|
|
3
|
+
} from 'native-base';
|
|
4
|
+
import testProps from '../../Functions/testProps.js';
|
|
5
|
+
import IconButton from './IconButton.js';
|
|
6
|
+
import Rotate from '../Icons/Rotate.js';
|
|
7
|
+
|
|
8
|
+
export default function ReloadButton(props, isTree = false) {
|
|
9
|
+
const {
|
|
10
|
+
iconProps ={},
|
|
11
|
+
self,
|
|
12
|
+
Repository,
|
|
13
|
+
} = props,
|
|
14
|
+
onPress = () => {
|
|
15
|
+
if (isTree) {
|
|
16
|
+
Repository.loadRootNodes(1);
|
|
17
|
+
} else {
|
|
18
|
+
Repository.reload();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
if (!Repository || Repository.isLocal) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return <IconButton
|
|
27
|
+
{...testProps('reloadBtn')}
|
|
28
|
+
{...props}
|
|
29
|
+
reference="reloadBtn"
|
|
30
|
+
parent={self}
|
|
31
|
+
icon={<Icon as={Rotate} {...iconProps} color="trueGray.600" />}
|
|
32
|
+
onPress={onPress}
|
|
33
|
+
tooltip="Reload"
|
|
34
|
+
ml={2}
|
|
35
|
+
/>;
|
|
36
|
+
}
|
|
37
|
+
|
|
@@ -1,30 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
Icon,
|
|
3
|
-
} from 'native-base';
|
|
4
|
-
import testProps from '../../Functions/testProps.js';
|
|
5
|
-
import IconButton from './IconButton.js';
|
|
6
|
-
import Rotate from '../Icons/Rotate.js';
|
|
1
|
+
import ReloadButton from './ReloadButton.js';
|
|
7
2
|
|
|
8
3
|
export default function ReloadPageButton(props) {
|
|
9
|
-
|
|
10
|
-
iconProps ={},
|
|
11
|
-
self,
|
|
12
|
-
Repository,
|
|
13
|
-
} = props;
|
|
14
|
-
|
|
15
|
-
if (!Repository || Repository.isLocal) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return <IconButton
|
|
20
|
-
{...testProps('reloadPageBtn')}
|
|
21
|
-
{...props}
|
|
22
|
-
reference="reloadPageBtn"
|
|
23
|
-
parent={self}
|
|
24
|
-
icon={<Icon as={Rotate} {...iconProps} color="trueGray.600" />}
|
|
25
|
-
onPress={() => Repository.reload()}
|
|
26
|
-
tooltip="Reload"
|
|
27
|
-
ml={2}
|
|
28
|
-
/>;
|
|
4
|
+
return <ReloadButton isTree={false} {...props} />;
|
|
29
5
|
}
|
|
30
6
|
|
|
@@ -976,13 +976,6 @@ function GridComponent(props) {
|
|
|
976
976
|
</Toolbar>;
|
|
977
977
|
}
|
|
978
978
|
}
|
|
979
|
-
|
|
980
|
-
const sizeProps = {};
|
|
981
|
-
if (!_.isNil(h)) {
|
|
982
|
-
sizeProps.h = h;
|
|
983
|
-
} else {
|
|
984
|
-
sizeProps.flex = flex ?? 1;
|
|
985
|
-
}
|
|
986
979
|
|
|
987
980
|
let grid = <FlatList
|
|
988
981
|
{...testProps('flatlist')}
|
|
@@ -1064,6 +1057,13 @@ function GridComponent(props) {
|
|
|
1064
1057
|
/>
|
|
1065
1058
|
</Modal>;
|
|
1066
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
const sizeProps = {};
|
|
1062
|
+
if (!_.isNil(h)) {
|
|
1063
|
+
sizeProps.h = h;
|
|
1064
|
+
} else {
|
|
1065
|
+
sizeProps.flex = flex ?? 1;
|
|
1066
|
+
}
|
|
1067
1067
|
|
|
1068
1068
|
grid = <Column
|
|
1069
1069
|
{...testProps(self)}
|
|
@@ -142,7 +142,9 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
142
142
|
if (!selection[0]) {
|
|
143
143
|
throw Error('Must select a parent node.');
|
|
144
144
|
}
|
|
145
|
-
|
|
145
|
+
const parent = selection[0];
|
|
146
|
+
addValues.parentId = parent.id;
|
|
147
|
+
addValues.depth = parent.depth +1;
|
|
146
148
|
} else {
|
|
147
149
|
// Set repository to sort by id DESC and switch to page 1, so this new entity is guaranteed to show up on the current page, even after saving
|
|
148
150
|
const currentSorter = Repository.sorters[0];
|
|
@@ -173,10 +175,13 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
173
175
|
setIsSaving(false);
|
|
174
176
|
setIsIgnoreNextSelectionChange(true);
|
|
175
177
|
setSelection([entity]);
|
|
178
|
+
if (getListeners().onAfterAdd) {
|
|
179
|
+
await getListeners().onAfterAdd(entity);
|
|
180
|
+
}
|
|
176
181
|
if (Repository.isAutoSave) {
|
|
177
182
|
// for isAutoSave Repositories, submit the handers right away
|
|
178
|
-
if (getListeners().
|
|
179
|
-
await getListeners().
|
|
183
|
+
if (getListeners().onAfterAddSave) {
|
|
184
|
+
await getListeners().onAfterAddSave(selection);
|
|
180
185
|
}
|
|
181
186
|
if (onAdd) {
|
|
182
187
|
await onAdd(entity);
|
|
@@ -377,8 +382,8 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
377
382
|
if (onAdd) {
|
|
378
383
|
await onAdd(selection);
|
|
379
384
|
}
|
|
380
|
-
if (getListeners().
|
|
381
|
-
await getListeners().
|
|
385
|
+
if (getListeners().onAfterAddSave) {
|
|
386
|
+
await getListeners().onAfterAddSave(selection);
|
|
382
387
|
}
|
|
383
388
|
setIsAdding(false);
|
|
384
389
|
setEditorMode(EDITOR_MODE__EDIT);
|
|
@@ -39,6 +39,7 @@ import getIconButtonFromConfig from '../../Functions/getIconButtonFromConfig.js'
|
|
|
39
39
|
import inArray from '../../Functions/inArray.js';
|
|
40
40
|
import testProps from '../../Functions/testProps.js';
|
|
41
41
|
import nbToRgb from '../../Functions/nbToRgb.js';
|
|
42
|
+
import ReloadTreeButton from '../Buttons/ReloadTreeButton.js';
|
|
42
43
|
import TreeNode, { DraggableTreeNode } from './TreeNode.js';
|
|
43
44
|
import FormPanel from '../Panel/FormPanel.js';
|
|
44
45
|
import Input from '../Form/Field/Input.js';
|
|
@@ -61,6 +62,7 @@ const DEPTH_INDENT_PX = 25;
|
|
|
61
62
|
function TreeComponent(props) {
|
|
62
63
|
const {
|
|
63
64
|
areRootsVisible = true,
|
|
65
|
+
autoLoadRootNodes = true,
|
|
64
66
|
extraParams = {}, // Additional params to send with each request ( e.g. { order: 'Categories.name ASC' })
|
|
65
67
|
getNodeText = (item) => { // extracts model/data and decides what the row text should be
|
|
66
68
|
if (Repository) {
|
|
@@ -232,6 +234,9 @@ function TreeComponent(props) {
|
|
|
232
234
|
}
|
|
233
235
|
},
|
|
234
236
|
onBeforeAdd = async () => {
|
|
237
|
+
// called during withEditor::doAdd, before the add operation is called
|
|
238
|
+
// returning false will cancel the add operation
|
|
239
|
+
|
|
235
240
|
// Load children before adding the new node
|
|
236
241
|
if (_.isEmpty(selection)) {
|
|
237
242
|
alert('Please select a parent node first.')
|
|
@@ -244,24 +249,32 @@ function TreeComponent(props) {
|
|
|
244
249
|
if (parent.hasChildren && !parent.areChildrenLoaded) {
|
|
245
250
|
await loadChildren(parentDatum);
|
|
246
251
|
}
|
|
252
|
+
|
|
253
|
+
// forceUpdate();
|
|
254
|
+
},
|
|
255
|
+
onAfterAdd = (entity) => {
|
|
256
|
+
// called during withEditor::doAdd, after the add operation is called
|
|
257
|
+
|
|
258
|
+
// Add the entity to the tree, show parent as hasChildren and expanded
|
|
259
|
+
const
|
|
260
|
+
parent = selection[0],
|
|
261
|
+
parentDatum = getNodeData(parent.id);
|
|
262
|
+
if (!parent.hasChildren) {
|
|
263
|
+
parent.hasChildren = true; // since we're adding a new child
|
|
264
|
+
}
|
|
247
265
|
if (!parentDatum.isExpanded) {
|
|
248
266
|
parentDatum.isExpanded = true;
|
|
249
267
|
}
|
|
268
|
+
|
|
269
|
+
buildRowToDatumMap();
|
|
250
270
|
forceUpdate();
|
|
251
271
|
},
|
|
252
|
-
|
|
253
|
-
// Expand the parent before showing the new node
|
|
254
|
-
const
|
|
255
|
-
entity = entities[0],
|
|
256
|
-
parentDatum = getNodeData(entity.parentId);
|
|
257
|
-
|
|
272
|
+
onAfterAddSave = (entities) => {
|
|
258
273
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
parentDatum.children.unshift(entityDatum);
|
|
262
|
-
forceUpdate();
|
|
274
|
+
// Update the datum with the new entity
|
|
275
|
+
return onAfterEdit(entities);
|
|
263
276
|
|
|
264
|
-
|
|
277
|
+
|
|
265
278
|
},
|
|
266
279
|
onBeforeEditSave = (entities) => {
|
|
267
280
|
onBeforeSave(entities);
|
|
@@ -910,6 +923,7 @@ function TreeComponent(props) {
|
|
|
910
923
|
onToggle={onToggle}
|
|
911
924
|
isDragMode={isDragMode}
|
|
912
925
|
isHighlighted={highlitedDatum === datum}
|
|
926
|
+
isSelected={isSelected}
|
|
913
927
|
|
|
914
928
|
// fields={fields}
|
|
915
929
|
/>;
|
|
@@ -1102,6 +1116,10 @@ function TreeComponent(props) {
|
|
|
1102
1116
|
Repository.setBaseParams(extraParams);
|
|
1103
1117
|
}
|
|
1104
1118
|
|
|
1119
|
+
if (autoLoadRootNodes) {
|
|
1120
|
+
Repository.loadRootNodes(1);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1105
1123
|
async function rebuildTree() {
|
|
1106
1124
|
setIsReady(false);
|
|
1107
1125
|
await buildAndSetTreeNodeData();
|
|
@@ -1117,6 +1135,7 @@ function TreeComponent(props) {
|
|
|
1117
1135
|
Repository.on('load', setFalse);
|
|
1118
1136
|
Repository.on('loadRootNodes', setFalse);
|
|
1119
1137
|
Repository.on('loadRootNodes', rebuildTree);
|
|
1138
|
+
Repository.on('add', rebuildTree);
|
|
1120
1139
|
Repository.on('changeFilters', reloadTree);
|
|
1121
1140
|
Repository.on('changeSorters', reloadTree);
|
|
1122
1141
|
|
|
@@ -1125,6 +1144,7 @@ function TreeComponent(props) {
|
|
|
1125
1144
|
Repository.off('load', setFalse);
|
|
1126
1145
|
Repository.off('loadRootNodes', setFalse);
|
|
1127
1146
|
Repository.off('loadRootNodes', rebuildTree);
|
|
1147
|
+
Repository.off('add', rebuildTree);
|
|
1128
1148
|
Repository.off('changeFilters', reloadTree);
|
|
1129
1149
|
Repository.off('changeSorters', reloadTree);
|
|
1130
1150
|
};
|
|
@@ -1147,6 +1167,7 @@ function TreeComponent(props) {
|
|
|
1147
1167
|
setWithEditListeners({ // Update withEdit's listeners on every render
|
|
1148
1168
|
onBeforeAdd,
|
|
1149
1169
|
onAfterAdd,
|
|
1170
|
+
onAfterAddSave,
|
|
1150
1171
|
onBeforeEditSave,
|
|
1151
1172
|
onAfterEdit,
|
|
1152
1173
|
onBeforeDeleteSave,
|
|
@@ -1168,9 +1189,16 @@ function TreeComponent(props) {
|
|
|
1168
1189
|
let treeFooterComponent = null;
|
|
1169
1190
|
if (!disableBottomToolbar) {
|
|
1170
1191
|
if (Repository && bottomToolbar === 'pagination' && !disablePagination && Repository.isPaginated) {
|
|
1171
|
-
treeFooterComponent = <PaginationToolbar
|
|
1192
|
+
treeFooterComponent = <PaginationToolbar
|
|
1193
|
+
Repository={Repository}
|
|
1194
|
+
self={self}
|
|
1195
|
+
toolbarItems={footerToolbarItemComponents}
|
|
1196
|
+
/>;
|
|
1172
1197
|
} else if (footerToolbarItemComponents.length) {
|
|
1173
|
-
treeFooterComponent = <Toolbar>
|
|
1198
|
+
treeFooterComponent = <Toolbar>
|
|
1199
|
+
<ReloadTreeButton Repository={Repository} self={self} />
|
|
1200
|
+
{footerToolbarItemComponents}
|
|
1201
|
+
</Toolbar>;
|
|
1174
1202
|
}
|
|
1175
1203
|
}
|
|
1176
1204
|
|
|
@@ -1207,7 +1235,7 @@ function TreeComponent(props) {
|
|
|
1207
1235
|
}
|
|
1208
1236
|
}}
|
|
1209
1237
|
>
|
|
1210
|
-
<ScrollView flex={1} w="100%">
|
|
1238
|
+
<ScrollView {...testProps('ScrollView')} flex={1} w="100%">
|
|
1211
1239
|
{!treeNodes?.length ?
|
|
1212
1240
|
<NoRecordsFound text={noneFoundText} onRefresh={reloadTree} /> :
|
|
1213
1241
|
treeNodes}
|
|
@@ -22,6 +22,7 @@ export default function TreeNode(props) {
|
|
|
22
22
|
onToggle,
|
|
23
23
|
isDragMode,
|
|
24
24
|
isHighlighted,
|
|
25
|
+
isSelected,
|
|
25
26
|
...propsToPass
|
|
26
27
|
} = props,
|
|
27
28
|
styles = UiGlobals.styles,
|
|
@@ -44,6 +45,7 @@ export default function TreeNode(props) {
|
|
|
44
45
|
return useMemo(() => {
|
|
45
46
|
|
|
46
47
|
return <Row
|
|
48
|
+
{...testProps('node' + (isSelected ? '-selected' : ''))}
|
|
47
49
|
alignItems="center"
|
|
48
50
|
flexGrow={1}
|
|
49
51
|
{...nodeProps}
|
|
@@ -54,7 +56,7 @@ export default function TreeNode(props) {
|
|
|
54
56
|
|
|
55
57
|
{isLoading ?
|
|
56
58
|
<Spinner px={2} /> :
|
|
57
|
-
(hasChildren && !isDragMode ? <IconButton icon={icon} onPress={() => onToggle(datum)} {...testProps('
|
|
59
|
+
(hasChildren && !isDragMode ? <IconButton icon={icon} onPress={() => onToggle(datum)} {...testProps('expandBtn')} /> : <Icon as={icon} px={2} />)}
|
|
58
60
|
|
|
59
61
|
<Text
|
|
60
62
|
overflow="hidden"
|
|
@@ -23,7 +23,7 @@ export function clickDuplicateButton(parentSelectors) {
|
|
|
23
23
|
return clickButton(parentSelectors, 'duplicateBtn');
|
|
24
24
|
}
|
|
25
25
|
export function clickReloadButton(parentSelectors) {
|
|
26
|
-
return clickButton(parentSelectors, '
|
|
26
|
+
return clickButton(parentSelectors, 'reloadBtn');
|
|
27
27
|
}
|
|
28
28
|
export function clickCloseButton(parentSelectors) {
|
|
29
29
|
return clickButton(parentSelectors, 'closeBtn');
|
|
@@ -40,6 +40,9 @@ export function clickYesButton(parentSelectors) {
|
|
|
40
40
|
export function clickNoButton(parentSelectors) {
|
|
41
41
|
return clickButton(parentSelectors, 'noBtn');
|
|
42
42
|
}
|
|
43
|
+
export function clickExpandButton(parentSelectors) {
|
|
44
|
+
return clickButton(parentSelectors, 'expandBtn');
|
|
45
|
+
}
|
|
43
46
|
export function clickXButton(parentSelectors) {
|
|
44
47
|
return clickButton(parentSelectors, 'xBtn');
|
|
45
48
|
}
|
|
@@ -25,6 +25,21 @@ import {
|
|
|
25
25
|
getModelFromGridSelector,
|
|
26
26
|
getGridRowSelectorById,
|
|
27
27
|
} from './grid_functions.js';
|
|
28
|
+
import {
|
|
29
|
+
hasNodeWithFieldValue,
|
|
30
|
+
getNodeWithFieldValue,
|
|
31
|
+
selectTreeNodeById,
|
|
32
|
+
selectTreeNodeIfNotAlreadySelectedById,
|
|
33
|
+
verifyTreeRecordDoesNotExistByValue,
|
|
34
|
+
verifyTreeRecordExistsByValue,
|
|
35
|
+
verifyTreeRecordExistsById,
|
|
36
|
+
verifyTreeRecordDoesNotExistById,
|
|
37
|
+
verifyTreeNodeIsSelectedById,
|
|
38
|
+
getModelFromTreeName,
|
|
39
|
+
getModelFromTreeSelector,
|
|
40
|
+
getTreeNodeSelectorById,
|
|
41
|
+
getFirstTreeRootNode,
|
|
42
|
+
} from './tree_functions.js';
|
|
28
43
|
import {
|
|
29
44
|
verifyNoErrorBox,
|
|
30
45
|
} from './common_functions.js';
|
|
@@ -59,6 +74,7 @@ import _ from 'lodash';
|
|
|
59
74
|
const $ = Cypress.$;
|
|
60
75
|
|
|
61
76
|
|
|
77
|
+
// Form fields
|
|
62
78
|
export function crudCombo(selector, newData, editData, schema, ancillaryData, level = 0) {
|
|
63
79
|
cy.then(() => {
|
|
64
80
|
Cypress.log({ name: 'crudCombo' });
|
|
@@ -92,28 +108,33 @@ export function crudTag(selector, newData, editData, schema, ancillaryData, leve
|
|
|
92
108
|
|
|
93
109
|
clickTrigger(selector);
|
|
94
110
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
// Grid
|
|
114
|
+
export function crudWindowedGridRecord(gridSelector, newData, editData, schema, ancillaryData, level = 0) {
|
|
115
|
+
|
|
99
116
|
cy.then(() => {
|
|
100
|
-
Cypress.log({ name: '
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
Cypress.log({ name: 'crudWindowedGridRecord ' + gridSelector });
|
|
118
|
+
});
|
|
119
|
+
|
|
103
120
|
getDomNode(gridSelector).scrollIntoView();
|
|
104
121
|
|
|
105
122
|
// add
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
addWindowedGridRecord(gridSelector, newData, schema, ancillaryData, level); // saves the id in @id
|
|
124
|
+
|
|
108
125
|
cy.get('@id' + level).then((id) => {
|
|
109
126
|
|
|
127
|
+
cy.then(() => {
|
|
128
|
+
Cypress.log({ name: 'crudWindowedGridRecord: continue thru CRUD ' + gridSelector });
|
|
129
|
+
});
|
|
130
|
+
|
|
110
131
|
// read
|
|
111
132
|
clickReloadButton(gridSelector);
|
|
112
133
|
cy.wait(1000); // allow time for grid to load
|
|
113
134
|
verifyGridRecordExistsById(gridSelector, id);
|
|
114
135
|
|
|
115
136
|
// edit
|
|
116
|
-
|
|
137
|
+
editWindowedGridRecord(gridSelector, editData, schema, id);
|
|
117
138
|
|
|
118
139
|
// delete
|
|
119
140
|
verifyGridRecordExistsById(gridSelector, id);
|
|
@@ -121,16 +142,16 @@ export function crudSideGridRecord(gridSelector, newData, editData, schema, anci
|
|
|
121
142
|
verifyGridRecordDoesNotExistById(gridSelector, id);
|
|
122
143
|
});
|
|
123
144
|
}
|
|
124
|
-
export function
|
|
145
|
+
export function crudInlineGridRecord(gridSelector, newData, editData, schema, ancillaryData, level = 0) {
|
|
125
146
|
|
|
126
147
|
cy.then(() => {
|
|
127
|
-
Cypress.log({ name: '
|
|
128
|
-
|
|
148
|
+
Cypress.log({ name: 'crudInlineGridRecord ' + gridSelector });
|
|
149
|
+
});
|
|
129
150
|
|
|
130
151
|
getDomNode(gridSelector).scrollIntoView();
|
|
131
152
|
|
|
132
153
|
// add
|
|
133
|
-
|
|
154
|
+
addInlineGridRecord(gridSelector, newData, schema, ancillaryData, level); // saves the id in @id
|
|
134
155
|
|
|
135
156
|
cy.get('@id' + level).then((id) => {
|
|
136
157
|
|
|
@@ -144,7 +165,7 @@ export function crudWindowedGridRecord(gridSelector, newData, editData, schema,
|
|
|
144
165
|
verifyGridRecordExistsById(gridSelector, id);
|
|
145
166
|
|
|
146
167
|
// edit
|
|
147
|
-
|
|
168
|
+
editInlineGridRecord(gridSelector, editData, schema, id);
|
|
148
169
|
|
|
149
170
|
// delete
|
|
150
171
|
verifyGridRecordExistsById(gridSelector, id);
|
|
@@ -152,22 +173,20 @@ export function crudWindowedGridRecord(gridSelector, newData, editData, schema,
|
|
|
152
173
|
verifyGridRecordDoesNotExistById(gridSelector, id);
|
|
153
174
|
});
|
|
154
175
|
}
|
|
155
|
-
export function
|
|
156
|
-
|
|
176
|
+
export function crudSideGridRecord(gridSelector, newData, editData, schema, ancillaryData, level = 0) {
|
|
177
|
+
// NOTE: the 'level' arg allows this fn to be called recursively
|
|
178
|
+
// and to use the @id alias correctly, keeping track of the level of recursion
|
|
179
|
+
// so the CRUD operations don't step on each other at different levels.
|
|
157
180
|
cy.then(() => {
|
|
158
|
-
Cypress.log({ name: '
|
|
159
|
-
|
|
160
|
-
|
|
181
|
+
Cypress.log({ name: 'crudSideGridRecord ' + gridSelector });
|
|
182
|
+
});
|
|
183
|
+
|
|
161
184
|
getDomNode(gridSelector).scrollIntoView();
|
|
162
185
|
|
|
163
186
|
// add
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
cy.get('@id' + level).then((id) => {
|
|
187
|
+
addGridRecord(gridSelector, newData, schema, ancillaryData, level); // saves the id in @id
|
|
167
188
|
|
|
168
|
-
|
|
169
|
-
Cypress.log({ name: 'crudWindowedGridRecord: continue thru CRUD ' + gridSelector });
|
|
170
|
-
});
|
|
189
|
+
cy.get('@id' + level).then((id) => {
|
|
171
190
|
|
|
172
191
|
// read
|
|
173
192
|
clickReloadButton(gridSelector);
|
|
@@ -175,7 +194,7 @@ export function crudInlineGridRecord(gridSelector, newData, editData, schema, an
|
|
|
175
194
|
verifyGridRecordExistsById(gridSelector, id);
|
|
176
195
|
|
|
177
196
|
// edit
|
|
178
|
-
|
|
197
|
+
editGridRecord(gridSelector, editData, schema, id);
|
|
179
198
|
|
|
180
199
|
// delete
|
|
181
200
|
verifyGridRecordExistsById(gridSelector, id);
|
|
@@ -384,7 +403,221 @@ export function switchToViewModeIfNecessary(editorSelector) {
|
|
|
384
403
|
}
|
|
385
404
|
|
|
386
405
|
|
|
387
|
-
//
|
|
406
|
+
// Tree
|
|
407
|
+
export function crudWindowedTreeRecord(treeSelector, newData, editData, schema, ancillaryData, level = 0) {
|
|
408
|
+
|
|
409
|
+
cy.then(() => {
|
|
410
|
+
Cypress.log({ name: 'crudWindowedTreeRecord ' + treeSelector });
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
getDomNode(treeSelector).scrollIntoView();
|
|
414
|
+
|
|
415
|
+
// add
|
|
416
|
+
addWindowedTreeRecord(treeSelector, newData, schema, ancillaryData, level); // saves the id in @id
|
|
417
|
+
|
|
418
|
+
cy.get('@id' + level).then((id) => {
|
|
419
|
+
|
|
420
|
+
cy.then(() => {
|
|
421
|
+
Cypress.log({ name: 'crudWindowedTreeRecord: continue thru CRUD ' + treeSelector });
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// read
|
|
425
|
+
clickReloadButton(treeSelector);
|
|
426
|
+
cy.wait(1000); // allow time for tree to load
|
|
427
|
+
verifyTreeRecordExistsById(treeSelector, id);
|
|
428
|
+
|
|
429
|
+
// edit
|
|
430
|
+
editWindowedTreeRecord(treeSelector, editData, schema, id);
|
|
431
|
+
|
|
432
|
+
// delete
|
|
433
|
+
verifyTreeRecordExistsById(treeSelector, id);
|
|
434
|
+
deleteTreeRecord(treeSelector, id);
|
|
435
|
+
verifyTreeRecordDoesNotExistById(treeSelector, id);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
export function crudSideTreeRecord(treeSelector, newData, editData, schema, ancillaryData, level = 0) {
|
|
439
|
+
// NOTE: the 'level' arg allows this fn to be called recursively
|
|
440
|
+
// and to use the @id alias correctly, keeping track of the level of recursion
|
|
441
|
+
// so the CRUD operations don't step on each other at different levels.
|
|
442
|
+
cy.then(() => {
|
|
443
|
+
Cypress.log({ name: 'crudSideTreeRecord ' + treeSelector });
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
getDomNode(treeSelector).scrollIntoView();
|
|
447
|
+
|
|
448
|
+
// add
|
|
449
|
+
addTreeRecord(treeSelector, newData, schema, ancillaryData, level); // saves the id in @id
|
|
450
|
+
|
|
451
|
+
cy.get('@id' + level).then((id) => {
|
|
452
|
+
|
|
453
|
+
// read
|
|
454
|
+
clickReloadButton(treeSelector);
|
|
455
|
+
cy.wait(1000); // allow time for tree to load
|
|
456
|
+
verifyTreeRecordExistsById(treeSelector, id);
|
|
457
|
+
|
|
458
|
+
// edit
|
|
459
|
+
editTreeRecord(treeSelector, editData, schema, id);
|
|
460
|
+
|
|
461
|
+
// delete
|
|
462
|
+
verifyTreeRecordExistsById(treeSelector, id);
|
|
463
|
+
deleteTreeRecord(treeSelector, id);
|
|
464
|
+
verifyTreeRecordDoesNotExistById(treeSelector, id);
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
export function addTreeRecord(treeSelector, fieldValues, schema, ancillaryData, level = 0) {
|
|
468
|
+
|
|
469
|
+
cy.then(() => {
|
|
470
|
+
Cypress.log({ name: 'addTreeRecord ' + treeSelector });
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
const
|
|
474
|
+
editorSelector = treeSelector + '/editor',
|
|
475
|
+
viewerSelector = editorSelector + '/viewer',
|
|
476
|
+
formSelector = editorSelector + '/form';
|
|
477
|
+
|
|
478
|
+
// BEGIN MOD
|
|
479
|
+
// select the root node
|
|
480
|
+
getFirstTreeRootNode(treeSelector).then ((rootNode) => {
|
|
481
|
+
|
|
482
|
+
// get the rootNodeId
|
|
483
|
+
const id = rootNode.attr('data-testid').split('-')[1];
|
|
484
|
+
selectTreeNodeIfNotAlreadySelectedById(treeSelector, id)
|
|
485
|
+
});
|
|
486
|
+
// END MOD
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
clickAddButton(treeSelector);
|
|
490
|
+
getDomNode(formSelector).should('exist');
|
|
491
|
+
|
|
492
|
+
fillForm(formSelector, fieldValues, schema, level +1);
|
|
493
|
+
cy.wait(500); // allow validator to enable save button
|
|
494
|
+
// TODO: Change this to wait until save button is enabled
|
|
495
|
+
|
|
496
|
+
let method = 'add';
|
|
497
|
+
if (schema.repository.isRemotePhantomMode) {
|
|
498
|
+
method = 'edit';
|
|
499
|
+
}
|
|
500
|
+
cy.intercept('POST', '**/' + method + '**').as('waiter');
|
|
501
|
+
clickSaveButton(formSelector); // it's labeled 'Add' in the form, but is really the save button
|
|
502
|
+
cy.wait('@waiter');
|
|
503
|
+
|
|
504
|
+
verifyNoErrorBox();
|
|
505
|
+
|
|
506
|
+
cy.wait(1000); // allow temp id to be replaced by real one
|
|
507
|
+
|
|
508
|
+
// Get and save id of new record
|
|
509
|
+
getDomNode([treeSelector, 'node-selected']).then((row) => {
|
|
510
|
+
const parent = row[0].parentNode;
|
|
511
|
+
cy.wrap(parent).invoke('attr', 'data-testid').then((testId) => {
|
|
512
|
+
const id = testId.split('-')[1];
|
|
513
|
+
cy.wrap(id).as('id' + level);
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
if (!_.isEmpty(ancillaryData)) {
|
|
518
|
+
_.each(ancillaryData, (data) => {
|
|
519
|
+
const
|
|
520
|
+
model = data.model,
|
|
521
|
+
Models = fixInflector(Inflector.camelize(Inflector.pluralize(model))),
|
|
522
|
+
gridType = data.gridType,
|
|
523
|
+
schema = data.schema,
|
|
524
|
+
newData = data.newData,
|
|
525
|
+
editData = data.editData,
|
|
526
|
+
ancillaryData = data.ancillaryData,
|
|
527
|
+
ancillaryGridSelector = formSelector + '/' + (gridType || Models + 'GridEditor');
|
|
528
|
+
crudWindowedGridRecord(ancillaryGridSelector, newData, editData, schema, ancillaryData, level+1);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
export function addWindowedTreeRecord(treeSelector, fieldValues, schema, ancillaryData, level = 0) {
|
|
533
|
+
// adds the record as normal, then closes the editor window
|
|
534
|
+
|
|
535
|
+
cy.then(() => {
|
|
536
|
+
Cypress.log({ name: 'addWindowedTreeRecord ' + treeSelector });
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
addTreeRecord(treeSelector, fieldValues, schema, ancillaryData, level);
|
|
540
|
+
|
|
541
|
+
cy.then(() => {
|
|
542
|
+
Cypress.log({ name: 'addWindowedTreeRecord: close window ' + treeSelector });
|
|
543
|
+
});
|
|
544
|
+
const formSelector = treeSelector + '/editor/form';
|
|
545
|
+
clickCloseButton(formSelector);
|
|
546
|
+
cy.wait(500); // allow window to close
|
|
547
|
+
// TODO: Change this to wait until window is closed
|
|
548
|
+
}
|
|
549
|
+
export function editTreeRecord(treeSelector, fieldValues, schema, id, level = 0) {
|
|
550
|
+
|
|
551
|
+
cy.then(() => {
|
|
552
|
+
Cypress.log({ name: 'editTreeRecord ' + treeSelector + ' ' + id});
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
selectTreeNodeIfNotAlreadySelectedById(treeSelector, id);
|
|
556
|
+
|
|
557
|
+
const
|
|
558
|
+
editorSelector = treeSelector + '/editor',
|
|
559
|
+
viewerSelector = editorSelector + '/viewer',
|
|
560
|
+
formSelector = editorSelector + '/form';
|
|
561
|
+
|
|
562
|
+
const treeName = getLastPartOfPath(treeSelector);
|
|
563
|
+
if (treeName.match(/SideTree/)) { // as opposed to 'SideA' -- we want the side editor, not particular sides of another editor
|
|
564
|
+
// side editor
|
|
565
|
+
// switch to Edit mode if necessary
|
|
566
|
+
clickToEditButtonIfExists(viewerSelector);
|
|
567
|
+
} else {
|
|
568
|
+
// windowed or inline editor
|
|
569
|
+
clickEditButton(treeSelector);
|
|
570
|
+
}
|
|
571
|
+
cy.wait(1500); // allow form to build
|
|
572
|
+
getDomNode(formSelector).should('exist');
|
|
573
|
+
|
|
574
|
+
fillForm(formSelector, fieldValues, schema, level +1);
|
|
575
|
+
cy.wait(500); // allow validator to enable save button
|
|
576
|
+
// TODO: Change this to wait until save button is enabled
|
|
577
|
+
|
|
578
|
+
cy.intercept('POST', '**/edit**').as('waiter');
|
|
579
|
+
clickSaveButton(formSelector);
|
|
580
|
+
cy.wait('@waiter');
|
|
581
|
+
|
|
582
|
+
verifyNoErrorBox();
|
|
583
|
+
// cy.wait(1000);
|
|
584
|
+
|
|
585
|
+
}
|
|
586
|
+
export function editWindowedTreeRecord(treeSelector, fieldValues, schema, id, level = 0) {
|
|
587
|
+
// edits the record as normal, then closes the editor window
|
|
588
|
+
|
|
589
|
+
cy.then(() => {
|
|
590
|
+
Cypress.log({ name: 'editWindowedTreeRecord ' + treeSelector + ' ' + id});
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
editTreeRecord(treeSelector, fieldValues, schema, id, level);
|
|
594
|
+
|
|
595
|
+
const formSelector = treeSelector + '/editor/form';
|
|
596
|
+
clickCloseButton(formSelector);
|
|
597
|
+
cy.wait(500); // allow window to close
|
|
598
|
+
// TODO: Change this to wait until window is closed
|
|
599
|
+
}
|
|
600
|
+
export function deleteTreeRecord(treeSelector, id) {
|
|
601
|
+
|
|
602
|
+
cy.then(() => {
|
|
603
|
+
Cypress.log({ name: 'deleteTreeRecord ' + treeSelector + ' ' + id });
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
selectTreeNodeIfNotAlreadySelectedById(treeSelector, id);
|
|
607
|
+
clickDeleteButton(treeSelector);
|
|
608
|
+
cy.wait(500); // allow confirmation box to appear
|
|
609
|
+
|
|
610
|
+
// Click OK on confirmation box
|
|
611
|
+
cy.intercept('POST', '**/delete**').as('waiter');
|
|
612
|
+
clickYesButton('AlertDialog');
|
|
613
|
+
cy.wait('@waiter');
|
|
614
|
+
|
|
615
|
+
verifyNoErrorBox();
|
|
616
|
+
// cy.wait(1000);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
// Manager screen
|
|
388
621
|
export function runClosureTreeControlledManagerScreenCrudTests(model, schema, newData, editData) {
|
|
389
622
|
|
|
390
623
|
const
|
|
@@ -474,11 +707,11 @@ export function runClosureTreeControlledManagerScreenCrudTests(model, schema, ne
|
|
|
474
707
|
});
|
|
475
708
|
|
|
476
709
|
}
|
|
477
|
-
export function runClosureTreeManagerScreenCrudTests(model, schema, newData, editData) {
|
|
710
|
+
export function runClosureTreeManagerScreenCrudTests(model, schema, newData, editData, ancillaryData) {
|
|
478
711
|
|
|
479
712
|
const
|
|
480
|
-
Models = Inflector.camelize(Inflector.pluralize(model)),
|
|
481
|
-
url = '/' + Inflector.dasherize(Inflector.underscore(Models));
|
|
713
|
+
Models = fixInflector(Inflector.camelize(Inflector.pluralize(model))),
|
|
714
|
+
url = '/' + fixInflector(Inflector.dasherize(Inflector.underscore(Models)));
|
|
482
715
|
|
|
483
716
|
describe(Models + 'Manager', () => {
|
|
484
717
|
|
|
@@ -492,44 +725,34 @@ export function runClosureTreeManagerScreenCrudTests(model, schema, newData, edi
|
|
|
492
725
|
});
|
|
493
726
|
});
|
|
494
727
|
|
|
495
|
-
afterEach(function () {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it('CRUD ClosureTree', function() {
|
|
501
|
-
|
|
502
|
-
const treeSelector = '/' + Models + 'TreeEditor';
|
|
728
|
+
// afterEach(function () {
|
|
729
|
+
// cy.saveLocalStorage();
|
|
730
|
+
// logout();
|
|
731
|
+
// });
|
|
503
732
|
|
|
504
|
-
|
|
505
|
-
cy.wait(500); // wait for tree to load
|
|
733
|
+
it('CRUD in full mode', function() {
|
|
506
734
|
|
|
735
|
+
const
|
|
736
|
+
managerSelector = '/' + Models + 'Manager',
|
|
737
|
+
treeSelector = '/' + Models + 'FilteredTreeEditor';
|
|
507
738
|
|
|
508
|
-
|
|
739
|
+
toFullMode(managerSelector);
|
|
740
|
+
cy.wait(500); // wait for grid to load
|
|
509
741
|
|
|
742
|
+
crudWindowedTreeRecord(treeSelector, newData, editData, schema, ancillaryData);
|
|
510
743
|
|
|
744
|
+
});
|
|
511
745
|
|
|
512
|
-
|
|
746
|
+
it('CRUD in side mode', function() {
|
|
513
747
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
// // cy.wrap(39).as('id');
|
|
518
|
-
// cy.get('@id').then((id) => {
|
|
748
|
+
const
|
|
749
|
+
managerSelector = '/' + Models + 'Manager',
|
|
750
|
+
treeSelector = '/' + Models + 'FilteredSideTreeEditor';
|
|
519
751
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
// cy.wait(1000); // allow time for tree to load
|
|
523
|
-
// verifyGridRecordExistsById(treeSelector, id);
|
|
752
|
+
toSideMode(managerSelector);
|
|
753
|
+
cy.wait(1000); // wait for grid to load
|
|
524
754
|
|
|
525
|
-
|
|
526
|
-
// editWindowedGridRecord(treeSelector, editData, schema, id);
|
|
527
|
-
|
|
528
|
-
// // delete
|
|
529
|
-
// verifyGridRecordExistsById(treeSelector, id);
|
|
530
|
-
// deleteGridRecord(treeSelector, id);
|
|
531
|
-
// verifyGridRecordDoesNotExistById(treeSelector, id);
|
|
532
|
-
// });
|
|
755
|
+
crudSideTreeRecord(treeSelector, newData, editData, schema, ancillaryData);
|
|
533
756
|
|
|
534
757
|
});
|
|
535
758
|
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fixInflector,
|
|
3
|
+
getLastPartOfPath,
|
|
4
|
+
} from './utilities.js';
|
|
5
|
+
import {
|
|
6
|
+
getDomNode,
|
|
7
|
+
getDomNodes,
|
|
8
|
+
} from './dom_functions.js';
|
|
9
|
+
import Inflector from 'inflector-js';
|
|
10
|
+
import _ from 'lodash';
|
|
11
|
+
const $ = Cypress.$;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// Get rows
|
|
16
|
+
export function hasNodeWithFieldValue(treeSelector, field, value) {
|
|
17
|
+
return getDomNodes([treeSelector, 'row', 'cell-' + field]).contains(value);
|
|
18
|
+
}
|
|
19
|
+
export function getNodeWithFieldValue(treeSelector, field, value) {
|
|
20
|
+
return getDomNodes([treeSelector, 'row', 'cell-' + field]).contains(value).then((cells) => {
|
|
21
|
+
if (!cells.length) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const cell = cells[0];
|
|
26
|
+
return $(cell).closest('[data-testid="row"]')[0];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function getFirstTreeRootNode(treeSelector) {
|
|
30
|
+
return cy.get('[data-testid="' + treeSelector + '"]:first ' +
|
|
31
|
+
'[data-testid="ScrollView"]:first > div > div:first'); // this is fragile!
|
|
32
|
+
}
|
|
33
|
+
// export function getNodeWithText(tree, text) {
|
|
34
|
+
// return getNodes(tree).contains(text);
|
|
35
|
+
// }
|
|
36
|
+
// export function getNodeWithId(tree, id) {
|
|
37
|
+
// return getNodes(tree, '[data-cy-recordid=' + id + ']');
|
|
38
|
+
// }
|
|
39
|
+
// export function getNodeWithIx(tree, ix) {
|
|
40
|
+
// return getNodes(tree, '[data-recordindex=' + ix + ']');
|
|
41
|
+
// }
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
// Select rows
|
|
45
|
+
export function selectTreeNodeById(treeSelector, id) {
|
|
46
|
+
cy.then(() => {
|
|
47
|
+
Cypress.log({ name: 'selectTreeNodeById ' + treeSelector + ' ' + id});
|
|
48
|
+
});
|
|
49
|
+
const rowSelector = getTreeNodeSelectorById(treeSelector, id);
|
|
50
|
+
getDomNode([treeSelector, rowSelector])
|
|
51
|
+
.click();
|
|
52
|
+
}
|
|
53
|
+
export function selectTreeNodeIfNotAlreadySelectedById(treeSelector, id) {
|
|
54
|
+
cy.then(() => {
|
|
55
|
+
Cypress.log({ name: 'selectTreeNodeIfNotAlreadySelectedById ' + treeSelector + ' ' + id});
|
|
56
|
+
});
|
|
57
|
+
const rowSelector = getTreeNodeSelectorById(treeSelector, id);
|
|
58
|
+
getDomNode([treeSelector, rowSelector]).then((row) => {
|
|
59
|
+
const found = row.find('[data-testid="node-selected"]')
|
|
60
|
+
if (!found.length) {
|
|
61
|
+
selectTreeNodeById(treeSelector, id);
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
// export function selectNodeWithText(tree, text) {
|
|
66
|
+
// getNodeWithText(tree, text).click(5, 5);
|
|
67
|
+
// }
|
|
68
|
+
// export function selectNodeWithIx(tree, ix) {
|
|
69
|
+
// getNodeWithIx(tree, ix).click(5, 5);
|
|
70
|
+
// }
|
|
71
|
+
// export function cmdClickNodeWithId(tree, id) {
|
|
72
|
+
// getNodeWithId(tree, id).click('left', { metaKey: true });
|
|
73
|
+
// }
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// // Double-click rows
|
|
77
|
+
// export function doubleClickNodeWithText(tree, text) {
|
|
78
|
+
// getNodeWithText(tree, text).dblclick();
|
|
79
|
+
// }
|
|
80
|
+
// export function doubleClickNodeWithId(tree, id) {
|
|
81
|
+
// getNodeWithId(tree, id).dblclick();
|
|
82
|
+
// }
|
|
83
|
+
// export function doubleClickNodeWithIx(tree, ix) {
|
|
84
|
+
// getNodeWithIx(tree, ix).dblclick();
|
|
85
|
+
// }
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
export function verifyTreeRecordDoesNotExistByValue(treeSelector, fieldValues, schema) {
|
|
89
|
+
const
|
|
90
|
+
field = schema.model.displayProperty,
|
|
91
|
+
value = fieldValues[field];
|
|
92
|
+
|
|
93
|
+
getDomNodes([treeSelector, 'row', 'cell-' + field])
|
|
94
|
+
.contains(value, { timeout: 500 })
|
|
95
|
+
.should('not.exist');
|
|
96
|
+
}
|
|
97
|
+
export function verifyTreeRecordExistsByValue(treeSelector, fieldValues, schema) {
|
|
98
|
+
const
|
|
99
|
+
field = schema.model.displayProperty,
|
|
100
|
+
value = fieldValues[field];
|
|
101
|
+
|
|
102
|
+
getDomNodes([treeSelector, 'row', 'cell-' + field])
|
|
103
|
+
.contains(value, { timeout: 500 })
|
|
104
|
+
.should('exist');
|
|
105
|
+
}
|
|
106
|
+
export function verifyTreeRecordExistsById(treeSelector, id) {
|
|
107
|
+
cy.then(() => {
|
|
108
|
+
Cypress.log({ name: 'verifyTreeRecordExistsById ' + treeSelector + ' ' + id });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const rowSelector = getTreeNodeSelectorById(treeSelector, id);
|
|
112
|
+
getDomNodes([treeSelector, rowSelector])
|
|
113
|
+
.should('exist');
|
|
114
|
+
}
|
|
115
|
+
export function verifyTreeRecordDoesNotExistById(treeSelector, id) {
|
|
116
|
+
cy.then(() => {
|
|
117
|
+
Cypress.log({ name: 'verifyTreeRecordDoesNotExistById ' + treeSelector + ' ' + id });
|
|
118
|
+
});
|
|
119
|
+
const rowSelector = getTreeNodeSelectorById(treeSelector, id);
|
|
120
|
+
getDomNodes([treeSelector, rowSelector])
|
|
121
|
+
.should('not.exist');
|
|
122
|
+
}
|
|
123
|
+
export function verifyTreeNodeIsSelectedById(treeSelector, id) {
|
|
124
|
+
cy.then(() => {
|
|
125
|
+
Cypress.log({ name: 'verifyTreeNodeIsSelectedById ' + treeSelector + ' ' + id});
|
|
126
|
+
});
|
|
127
|
+
const rowSelector = getTreeNodeSelectorById(treeSelector, id);
|
|
128
|
+
getDomNodes([treeSelector, rowSelector, 'node-selected'])
|
|
129
|
+
.should('exist');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
// export function addRecordWithInlineEditor(tree, fieldValues, schema) {
|
|
137
|
+
// clickTreeAddButton(tree, true);
|
|
138
|
+
// fillInlineForm(tree, fieldValues, schema);
|
|
139
|
+
// cy.route('POST', '**/extAdd**').as('addWaiter');
|
|
140
|
+
// submitInlineForm(tree);
|
|
141
|
+
// cy.wait('@addWaiter');
|
|
142
|
+
// verifyNoErrorBox();
|
|
143
|
+
// getSelectedNodeId(tree); // Adds @id alias
|
|
144
|
+
// cy.wait(1000);
|
|
145
|
+
// }
|
|
146
|
+
// export function addRecordWithWindowedEditor(tree, editorCls, fieldValues, schema) {
|
|
147
|
+
// clickTreeAddButton(tree, true);
|
|
148
|
+
// fillWindowedForm(editorCls, fieldValues, schema);
|
|
149
|
+
// cy.route('POST', '**/extAdd**').as('addWaiter');
|
|
150
|
+
// submitWindowedForm(editorCls);
|
|
151
|
+
// cy.wait('@addWaiter');
|
|
152
|
+
// verifyNoErrorBox();
|
|
153
|
+
// getSelectedNodeId(tree); // Adds @id alias
|
|
154
|
+
// cy.wait(1000);
|
|
155
|
+
// }
|
|
156
|
+
// export function editRecordWithInlineEditor(tree, fieldValues, schema) {
|
|
157
|
+
// cy.get("@id").then((id) => {
|
|
158
|
+
// doubleClickNodeWithId(tree, id);
|
|
159
|
+
// fillInlineForm(tree, fieldValues, schema);
|
|
160
|
+
// cy.route('POST', '**/extEdit**').as('editWaiter');
|
|
161
|
+
// submitInlineForm(tree);
|
|
162
|
+
// cy.wait('@editWaiter');
|
|
163
|
+
// verifyNoErrorBox();
|
|
164
|
+
// cy.wait(500);
|
|
165
|
+
// });
|
|
166
|
+
// }
|
|
167
|
+
// export function editRecordWithWindowedEditor(tree, editorCls, fieldValues, schema) {
|
|
168
|
+
// cy.get("@id").then((id) => {
|
|
169
|
+
// doubleClickNodeWithId(tree, id);
|
|
170
|
+
// fillWindowedForm(editorCls, fieldValues, schema);
|
|
171
|
+
// cy.route('POST', '**/extEdit**').as('editWaiter');
|
|
172
|
+
// submitWindowedForm(editorCls);
|
|
173
|
+
// cy.wait('@editWaiter');
|
|
174
|
+
// verifyNoErrorBox();
|
|
175
|
+
// });
|
|
176
|
+
// }
|
|
177
|
+
// export function removeRecord(tree) {
|
|
178
|
+
// cy.get("@id").then((id) => {
|
|
179
|
+
// cy.wait(500);
|
|
180
|
+
// clickTreeRemoveButton(tree);
|
|
181
|
+
// cy.route('POST', '**/extDelete**').as('removeWaiter');
|
|
182
|
+
// clickMessageBoxDefaultButton();
|
|
183
|
+
// cy.wait('@removeWaiter');
|
|
184
|
+
// verifyNoErrorBox();
|
|
185
|
+
// });
|
|
186
|
+
// }
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
// Tree Utilities
|
|
190
|
+
export function getModelFromTreeName(treeName) {
|
|
191
|
+
// try to match with something like 'EquipmentFilteredTreeEditor'
|
|
192
|
+
const
|
|
193
|
+
pattern = '^' + // start
|
|
194
|
+
'([\\w]+?)' + // model name
|
|
195
|
+
'(?=Filtered|Inline|Side|Tree)' + // positive lookahead to guarantee one of these is the next word
|
|
196
|
+
'(Filtered)?' + // optional
|
|
197
|
+
'(Inline)?' + // optional
|
|
198
|
+
'(Side)?' + // optional
|
|
199
|
+
'Tree' + // required
|
|
200
|
+
'(Editor)?' + // optional
|
|
201
|
+
'(Side[AB])?' + // optional
|
|
202
|
+
'$', // end
|
|
203
|
+
regex = new RegExp(pattern),
|
|
204
|
+
match = treeName.match(regex);
|
|
205
|
+
return match?.length ? match[1] : null;
|
|
206
|
+
}
|
|
207
|
+
export function getModelFromTreePath(treePath) {
|
|
208
|
+
// try to match with something like '...__eq_manufacturer_id/tree'
|
|
209
|
+
let
|
|
210
|
+
pattern = '^' + // start
|
|
211
|
+
'.*' + // previous selector path (ignore)
|
|
212
|
+
'(?=__)' + // positive lookahead to guarantee '__' is the next word
|
|
213
|
+
'__' + // required
|
|
214
|
+
'([A-Za-z_]+)' + // field name (model name underscored, singularized)
|
|
215
|
+
'([\\d]+)?' + // optional (digit, e.g. eq_engine_model1_id)
|
|
216
|
+
'_id/(combo/)?tree' + // required
|
|
217
|
+
'$', // end
|
|
218
|
+
regex = new RegExp(pattern),
|
|
219
|
+
match = treePath.match(regex);
|
|
220
|
+
if (!match) {
|
|
221
|
+
// try to match with something like '.../work_orders__equipment/combo/tree"'
|
|
222
|
+
pattern = '^' + // start
|
|
223
|
+
'.*' + // previous selector path (ignore)
|
|
224
|
+
'(?=__)' + // positive lookahead to guarantee '__' is the next word
|
|
225
|
+
'__' + // required
|
|
226
|
+
'([A-Za-z_]+)' + // field name (model name underscored, pluralized)
|
|
227
|
+
'/(combo/)?tree' + // required
|
|
228
|
+
'$', // end
|
|
229
|
+
regex = new RegExp(pattern);
|
|
230
|
+
match = treePath.match(regex);
|
|
231
|
+
}
|
|
232
|
+
return match?.length ? match[1] : null;
|
|
233
|
+
}
|
|
234
|
+
export function getModelFromTreeSelector(treeSelector) {
|
|
235
|
+
const treeName = getLastPartOfPath(treeSelector);
|
|
236
|
+
let model = getModelFromTreeName(treeName);
|
|
237
|
+
if (!model) {
|
|
238
|
+
model = getModelFromTreePath(treeSelector);
|
|
239
|
+
if (model) {
|
|
240
|
+
model = fixInflector(Inflector.camelize(Inflector.pluralize(model)));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return model;
|
|
244
|
+
}
|
|
245
|
+
export function getTreeNodeSelectorById(treeSelector, id) {
|
|
246
|
+
const
|
|
247
|
+
model = getModelFromTreeSelector(treeSelector);
|
|
248
|
+
|
|
249
|
+
if (!model) {
|
|
250
|
+
debugger;
|
|
251
|
+
}
|
|
252
|
+
const inflected = fixInflector(Inflector.camelize(Inflector.pluralize(model)));
|
|
253
|
+
return inflected + '-' + id;
|
|
254
|
+
}
|