@nocobase/plugin-workflow-test 0.20.0-alpha.9 → 0.21.0-alpha.2
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/dist/e2e/e2ePageObjectModel.d.ts +26 -10
- package/dist/e2e/e2ePageObjectModel.js +80 -44
- package/dist/e2e/e2eUtils.d.ts +9 -0
- package/dist/e2e/e2eUtils.js +67 -3
- package/dist/externalVersion.js +7 -5
- package/dist/server/index.js +22 -1
- package/package.json +2 -2
- package/src/e2e/e2ePageObjectModel.ts +101 -43
- package/src/e2e/e2eUtils.ts +165 -1
- package/src/server/index.ts +29 -2
|
@@ -42,29 +42,45 @@ export declare class ApprovalTriggerNode {
|
|
|
42
42
|
nodeTitle: Locator;
|
|
43
43
|
nodeConfigure: Locator;
|
|
44
44
|
collectionDropDown: Locator;
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
dataBlocksInitiationRadio: Locator;
|
|
46
|
+
dataBlocksAndGlobalApprovalBlocksInitiationRadio: Locator;
|
|
47
|
+
allowedToBeWithdrawnCheckbox: Locator;
|
|
48
|
+
goToconfigureButton: Locator;
|
|
47
49
|
addBlockButton: Locator;
|
|
48
50
|
addApplyFormMenu: Locator;
|
|
49
51
|
configureFieldsButton: Locator;
|
|
50
52
|
configureActionsButton: Locator;
|
|
51
53
|
saveDraftSwitch: Locator;
|
|
54
|
+
submitButton: Locator;
|
|
55
|
+
cancelButton: Locator;
|
|
52
56
|
addNodeButton: Locator;
|
|
53
57
|
constructor(page: Page, triggerName: string, collectionName: string);
|
|
54
58
|
}
|
|
55
|
-
export declare class
|
|
59
|
+
export declare class ApprovalPassthroughModeNode {
|
|
56
60
|
readonly page: Page;
|
|
57
61
|
node: Locator;
|
|
58
62
|
nodeTitle: Locator;
|
|
59
63
|
nodeConfigure: Locator;
|
|
64
|
+
addAssigneesButton: Locator;
|
|
60
65
|
assigneesDropDown: Locator;
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
OrRadio: Locator;
|
|
67
|
+
AndRadio: Locator;
|
|
68
|
+
votingRadio: Locator;
|
|
69
|
+
parallellyRadio: Locator;
|
|
70
|
+
sequentiallyRadio: Locator;
|
|
71
|
+
goToconfigureButton: Locator;
|
|
63
72
|
addBlockButton: Locator;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
addDetailsMenu: Locator;
|
|
74
|
+
detailsConfigureFieldsButton: Locator;
|
|
75
|
+
addActionsMenu: Locator;
|
|
76
|
+
actionsConfigureFieldsButton: Locator;
|
|
77
|
+
actionsConfigureActionsButton: Locator;
|
|
78
|
+
addApproveButton: Locator;
|
|
79
|
+
addRejectButton: Locator;
|
|
80
|
+
addReturnButton: Locator;
|
|
81
|
+
addNodeResult: Locator;
|
|
82
|
+
submitButton: Locator;
|
|
83
|
+
cancelButton: Locator;
|
|
68
84
|
addNodeButton: Locator;
|
|
69
85
|
constructor(page: Page, nodeName: string, collectionName: string);
|
|
70
86
|
}
|
|
@@ -274,7 +290,7 @@ declare const _default: {
|
|
|
274
290
|
WorkflowManagement: typeof WorkflowManagement;
|
|
275
291
|
WorkflowListRecords: typeof WorkflowListRecords;
|
|
276
292
|
ApprovalTriggerNode: typeof ApprovalTriggerNode;
|
|
277
|
-
|
|
293
|
+
ApprovalPassthroughModeNode: typeof ApprovalPassthroughModeNode;
|
|
278
294
|
ScheduleTriggerNode: typeof ScheduleTriggerNode;
|
|
279
295
|
CollectionTriggerNode: typeof CollectionTriggerNode;
|
|
280
296
|
FormEventTriggerNode: typeof FormEventTriggerNode;
|
|
@@ -18,7 +18,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
18
18
|
var e2ePageObjectModel_exports = {};
|
|
19
19
|
__export(e2ePageObjectModel_exports, {
|
|
20
20
|
AggregateNode: () => AggregateNode,
|
|
21
|
-
|
|
21
|
+
ApprovalPassthroughModeNode: () => ApprovalPassthroughModeNode,
|
|
22
22
|
ApprovalTriggerNode: () => ApprovalTriggerNode,
|
|
23
23
|
ClculationNode: () => ClculationNode,
|
|
24
24
|
CollectionTriggerNode: () => CollectionTriggerNode,
|
|
@@ -112,61 +112,97 @@ class ApprovalTriggerNode {
|
|
|
112
112
|
nodeTitle;
|
|
113
113
|
nodeConfigure;
|
|
114
114
|
collectionDropDown;
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
dataBlocksInitiationRadio;
|
|
116
|
+
dataBlocksAndGlobalApprovalBlocksInitiationRadio;
|
|
117
|
+
allowedToBeWithdrawnCheckbox;
|
|
118
|
+
goToconfigureButton;
|
|
117
119
|
addBlockButton;
|
|
118
120
|
addApplyFormMenu;
|
|
119
121
|
configureFieldsButton;
|
|
120
122
|
configureActionsButton;
|
|
121
123
|
saveDraftSwitch;
|
|
124
|
+
submitButton;
|
|
125
|
+
cancelButton;
|
|
122
126
|
addNodeButton;
|
|
123
127
|
constructor(page, triggerName, collectionName) {
|
|
124
128
|
this.page = page;
|
|
125
129
|
this.node = page.getByText("TriggeraConfigure");
|
|
126
130
|
this.nodeTitle = page.locator("textarea").filter({ hasText: triggerName });
|
|
127
131
|
this.nodeConfigure = page.getByRole("button", { name: "Configure" });
|
|
128
|
-
this.collectionDropDown = page.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
-
|
|
132
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
133
|
+
this.dataBlocksInitiationRadio = page.getByLabel("Initiate and approve in data blocks only");
|
|
134
|
+
this.dataBlocksAndGlobalApprovalBlocksInitiationRadio = page.getByLabel(
|
|
135
|
+
"Initiate and approve in both data blocks and global approval blocks"
|
|
136
|
+
);
|
|
137
|
+
this.allowedToBeWithdrawnCheckbox = page.getByLabel("Allowed to be withdrawn");
|
|
138
|
+
this.goToconfigureButton = page.getByRole("button", { name: "Go to configure" });
|
|
139
|
+
this.addBlockButton = page.getByLabel(`schema-initializer-Grid-ApprovalApplyAddBlockButton-${collectionName}`);
|
|
132
140
|
this.addApplyFormMenu = page.getByRole("menuitem", { name: "Apply form" });
|
|
133
|
-
this.configureFieldsButton = page.
|
|
134
|
-
this.configureActionsButton = page.
|
|
135
|
-
|
|
141
|
+
this.configureFieldsButton = page.getByLabel(`schema-initializer-Grid-form:configureFields-${collectionName}`);
|
|
142
|
+
this.configureActionsButton = page.getByLabel(
|
|
143
|
+
`schema-initializer-ActionBar-ApprovalApplyAddActionButton-${collectionName}`
|
|
136
144
|
);
|
|
137
145
|
this.saveDraftSwitch = page.getByRole("menuitem", { name: "Save draft" }).getByRole("switch");
|
|
138
|
-
this.
|
|
146
|
+
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
147
|
+
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
148
|
+
this.addNodeButton = this.addNodeButton = page.getByLabel("add-button", { exact: true });
|
|
139
149
|
}
|
|
140
150
|
}
|
|
141
|
-
class
|
|
151
|
+
class ApprovalPassthroughModeNode {
|
|
142
152
|
page;
|
|
143
153
|
node;
|
|
144
154
|
nodeTitle;
|
|
145
155
|
nodeConfigure;
|
|
156
|
+
addAssigneesButton;
|
|
146
157
|
assigneesDropDown;
|
|
147
|
-
|
|
148
|
-
|
|
158
|
+
OrRadio;
|
|
159
|
+
AndRadio;
|
|
160
|
+
votingRadio;
|
|
161
|
+
parallellyRadio;
|
|
162
|
+
sequentiallyRadio;
|
|
163
|
+
goToconfigureButton;
|
|
149
164
|
addBlockButton;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
addDetailsMenu;
|
|
166
|
+
detailsConfigureFieldsButton;
|
|
167
|
+
addActionsMenu;
|
|
168
|
+
actionsConfigureFieldsButton;
|
|
169
|
+
actionsConfigureActionsButton;
|
|
170
|
+
addApproveButton;
|
|
171
|
+
addRejectButton;
|
|
172
|
+
addReturnButton;
|
|
173
|
+
addNodeResult;
|
|
174
|
+
submitButton;
|
|
175
|
+
cancelButton;
|
|
154
176
|
addNodeButton;
|
|
155
177
|
constructor(page, nodeName, collectionName) {
|
|
156
178
|
this.page = page;
|
|
157
|
-
this.node = page.
|
|
158
|
-
this.nodeTitle = page.
|
|
159
|
-
this.nodeConfigure = page.getByRole("button", { name: "Configure" });
|
|
160
|
-
this.
|
|
161
|
-
this.
|
|
162
|
-
this.
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
165
|
-
this.
|
|
166
|
-
this.
|
|
167
|
-
|
|
179
|
+
this.node = page.getByLabel(`Approval-${nodeName}`, { exact: true });
|
|
180
|
+
this.nodeTitle = page.getByLabel(`Approval-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
181
|
+
this.nodeConfigure = page.getByLabel(`Approval-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
182
|
+
this.addAssigneesButton = page.getByRole("button", { name: "plus Add assignee" });
|
|
183
|
+
this.assigneesDropDown = page.getByTestId("select-single");
|
|
184
|
+
this.OrRadio = page.getByLabel("Or", { exact: true });
|
|
185
|
+
this.AndRadio = page.getByLabel("And", { exact: true });
|
|
186
|
+
this.votingRadio = page.getByLabel("Voting", { exact: true });
|
|
187
|
+
this.parallellyRadio = page.getByLabel("Parallelly", { exact: true });
|
|
188
|
+
this.sequentiallyRadio = page.getByLabel("Sequentially", { exact: true });
|
|
189
|
+
this.goToconfigureButton = page.getByRole("button", { name: "Go to configure" });
|
|
190
|
+
this.addBlockButton = page.getByLabel("schema-initializer-Grid-ApprovalProcessAddBlockButton-workflows");
|
|
191
|
+
this.addDetailsMenu = page.getByRole("menuitem", { name: "Details" });
|
|
192
|
+
this.detailsConfigureFieldsButton = page.getByLabel(
|
|
193
|
+
`schema-initializer-Grid-ReadPrettyFormItemInitializers-${collectionName}`
|
|
168
194
|
);
|
|
169
|
-
this.
|
|
195
|
+
this.addActionsMenu = page.getByRole("menuitem", { name: "Actions" }).getByRole("switch");
|
|
196
|
+
this.actionsConfigureFieldsButton = page.getByLabel("schema-initializer-Grid-FormItemInitializers-approvalRecords");
|
|
197
|
+
this.actionsConfigureActionsButton = page.getByLabel(
|
|
198
|
+
"schema-initializer-ActionBar-ApprovalProcessAddActionButton-approvalRecords"
|
|
199
|
+
);
|
|
200
|
+
this.addApproveButton = page.getByRole("menuitem", { name: "Approve" }).getByRole("switch");
|
|
201
|
+
this.addRejectButton = page.getByRole("menuitem", { name: "Reject" }).getByRole("switch");
|
|
202
|
+
this.addReturnButton = page.getByRole("menuitem", { name: "Return" }).getByRole("switch");
|
|
203
|
+
this.addNodeResult = page.getByRole("menuitem", { name: "Node result right" });
|
|
204
|
+
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
205
|
+
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
170
206
|
this.addNodeButton = page.getByLabel(`add-button-calculation-${nodeName}`, { exact: true });
|
|
171
207
|
}
|
|
172
208
|
}
|
|
@@ -193,7 +229,7 @@ class ScheduleTriggerNode {
|
|
|
193
229
|
this.startTimeEntryBox = page.getByPlaceholder("Select date");
|
|
194
230
|
this.RrpeatModeDropdown = page.getByLabel("block-item-RepeatField-workflows-Repeat mode");
|
|
195
231
|
this.dataTableTimeFieldOptions = page.getByLabel("Based on date field of collection");
|
|
196
|
-
this.collectionDropDown = page.
|
|
232
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
197
233
|
this.startTimeDropdown = page.getByLabel("block-item-OnField-workflows-Starts on");
|
|
198
234
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
199
235
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
@@ -215,7 +251,7 @@ class CollectionTriggerNode {
|
|
|
215
251
|
this.node = page.getByLabel(`Trigger-${triggerName}`);
|
|
216
252
|
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole("textbox");
|
|
217
253
|
this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole("button", { name: "Configure" });
|
|
218
|
-
this.collectionDropDown = page.
|
|
254
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
219
255
|
this.triggerOnDropdown = page.getByLabel("block-item-Select-workflows-Trigger on").getByRole("button", { name: "Trigger on" });
|
|
220
256
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
221
257
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
@@ -237,7 +273,7 @@ class FormEventTriggerNode {
|
|
|
237
273
|
this.node = page.getByLabel(`Trigger-${triggerName}`);
|
|
238
274
|
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole("textbox");
|
|
239
275
|
this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole("button", { name: "Configure" });
|
|
240
|
-
this.collectionDropDown = page.
|
|
276
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
241
277
|
this.relationalDataDropdown = page.getByTestId("select-field-Preload associations");
|
|
242
278
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
243
279
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
@@ -288,7 +324,7 @@ class QueryRecordNode {
|
|
|
288
324
|
this.node = page.getByLabel(`Query record-${nodeName}`, { exact: true });
|
|
289
325
|
this.nodeTitle = page.getByLabel(`Query record-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
290
326
|
this.nodeConfigure = page.getByLabel(`Query record-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
291
|
-
this.collectionDropDown = page.
|
|
327
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
292
328
|
this.allowMultipleDataBoxesForResults = page.getByLabel("Allow multiple records as");
|
|
293
329
|
this.addSortFieldsButton = page.getByRole("button", { name: "plus Add sort field" });
|
|
294
330
|
this.pageNumberEditBox = page.getByLabel("variable-constant");
|
|
@@ -315,7 +351,7 @@ class CreateRecordNode {
|
|
|
315
351
|
this.node = page.getByLabel(`Create record-${nodeName}`, { exact: true });
|
|
316
352
|
this.nodeTitle = page.getByLabel(`Create record-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
317
353
|
this.nodeConfigure = page.getByLabel(`Create record-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
318
|
-
this.collectionDropDown = page.
|
|
354
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
319
355
|
this.addFieldsButton = page.getByRole("button", { name: "plus Add field" });
|
|
320
356
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
321
357
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
@@ -339,7 +375,7 @@ class UpdateRecordNode {
|
|
|
339
375
|
this.node = page.getByLabel(`Update record-${nodeName}`, { exact: true });
|
|
340
376
|
this.nodeTitle = page.getByLabel(`Update record-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
341
377
|
this.nodeConfigure = page.getByLabel(`Update record-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
342
|
-
this.collectionDropDown = page.
|
|
378
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
343
379
|
this.batchUpdateModeRadio = page.getByLabel("block-item-IndividualHooksRadioWithTooltip-workflows-Update mode").getByLabel("Update in a batch");
|
|
344
380
|
this.articleByArticleUpdateModeRadio = page.getByLabel("block-item-IndividualHooksRadioWithTooltip-workflows-Update mode").getByLabel("Update one by one");
|
|
345
381
|
this.addFieldsButton = page.getByRole("button", { name: "plus Add field" });
|
|
@@ -362,7 +398,7 @@ class DeleteRecordNode {
|
|
|
362
398
|
this.node = page.getByLabel(`Delete record-${nodeName}`, { exact: true });
|
|
363
399
|
this.nodeTitle = page.getByLabel(`Delete record-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
364
400
|
this.nodeConfigure = page.getByLabel(`Delete record-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
365
|
-
this.collectionDropDown = page.
|
|
401
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Collection").locator(".ant-select-selection-search-input");
|
|
366
402
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
367
403
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
368
404
|
this.addNodeButton = page.getByLabel(`add-button-delete-${nodeName}`, { exact: true });
|
|
@@ -398,10 +434,8 @@ class AggregateNode {
|
|
|
398
434
|
this.minRadio = page.getByLabel("MIN", { exact: true });
|
|
399
435
|
this.dataTableDataRadio = page.getByLabel("Data of collection");
|
|
400
436
|
this.linkedDataTableDataRadio = page.getByLabel("Data of associated collection");
|
|
401
|
-
this.collectionDropDown = page.
|
|
402
|
-
this.aggregatedFieldDropDown = page.locator(
|
|
403
|
-
'input.ant-select-selection-search-input[role="combobox"][aria-haspopup="listbox"]'
|
|
404
|
-
);
|
|
437
|
+
this.collectionDropDown = page.getByLabel("block-item-DataSourceCollectionCascader-workflows-Data of collection").locator(".ant-select-selection-search-input");
|
|
438
|
+
this.aggregatedFieldDropDown = page.getByLabel("block-item-FieldsSelect-workflows-Field to aggregate").locator(".ant-select-selection-search-input");
|
|
405
439
|
this.distinctCheckBox = page.getByLabel("block-item-Checkbox-workflows-Distinct").locator('input.ant-checkbox-input[type="checkbox"]');
|
|
406
440
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
407
441
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
@@ -431,7 +465,9 @@ class ManualNode {
|
|
|
431
465
|
this.nodeConfigure = page.getByLabel(`Manual-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
432
466
|
this.assigneesDropDown = page.getByTestId("select-single");
|
|
433
467
|
this.configureUserInterfaceButton = page.getByRole("button", { name: "Configure user interface" });
|
|
434
|
-
this.addBlockButton = page.getByLabel(
|
|
468
|
+
this.addBlockButton = page.getByLabel(
|
|
469
|
+
"schema-initializer-Grid-workflowManual:popup:configureUserInterface:addBlock-workflows"
|
|
470
|
+
);
|
|
435
471
|
this.triggerDataMenu = page.getByRole("menuitem", { name: "Trigger data" });
|
|
436
472
|
this.nodeDataMenu = page.getByRole("menuitem", { name: "Node result right" });
|
|
437
473
|
this.customFormMenu = page.getByRole("menuitem", { name: "Custom form" });
|
|
@@ -550,7 +586,7 @@ var e2ePageObjectModel_default = module.exports = {
|
|
|
550
586
|
WorkflowManagement,
|
|
551
587
|
WorkflowListRecords,
|
|
552
588
|
ApprovalTriggerNode,
|
|
553
|
-
|
|
589
|
+
ApprovalPassthroughModeNode,
|
|
554
590
|
ScheduleTriggerNode,
|
|
555
591
|
CollectionTriggerNode,
|
|
556
592
|
FormEventTriggerNode,
|
|
@@ -569,7 +605,7 @@ var e2ePageObjectModel_default = module.exports = {
|
|
|
569
605
|
// Annotate the CommonJS export names for ESM import in node:
|
|
570
606
|
0 && (module.exports = {
|
|
571
607
|
AggregateNode,
|
|
572
|
-
|
|
608
|
+
ApprovalPassthroughModeNode,
|
|
573
609
|
ApprovalTriggerNode,
|
|
574
610
|
ClculationNode,
|
|
575
611
|
CollectionTriggerNode,
|
package/dist/e2e/e2eUtils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Page } from '@nocobase/test/e2e';
|
|
1
2
|
export declare const apiCreateWorkflow: (data: any) => Promise<any>;
|
|
2
3
|
export declare const apiUpdateWorkflow: (id: number, data: any) => Promise<any>;
|
|
3
4
|
export declare const apiDeleteWorkflow: (id: number) => Promise<any>;
|
|
@@ -13,6 +14,10 @@ export declare const apiGetList: (collectionName: string) => Promise<any>;
|
|
|
13
14
|
export declare const apiFilterList: (collectionName: string, filter: string) => Promise<any>;
|
|
14
15
|
export declare const apiCreateRecordTriggerFormEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
15
16
|
export declare const apiSubmitRecordTriggerFormEvent: (triggerWorkflows: string, data: any) => Promise<any>;
|
|
17
|
+
export declare const apiGetDataSourceCount: () => Promise<any>;
|
|
18
|
+
export declare const apiCreateRecordTriggerActionEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
19
|
+
export declare const apiApplyApprovalEvent: (data: any) => Promise<any>;
|
|
20
|
+
export declare const userLogin: (page: Page, approvalUserEmail: string, approvalUser: string) => Promise<Page>;
|
|
16
21
|
declare const _default: {
|
|
17
22
|
apiCreateWorkflow: (data: any) => Promise<any>;
|
|
18
23
|
apiUpdateWorkflow: (id: number, data: any) => Promise<any>;
|
|
@@ -29,5 +34,9 @@ declare const _default: {
|
|
|
29
34
|
apiCreateRecordTriggerFormEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
30
35
|
apiSubmitRecordTriggerFormEvent: (triggerWorkflows: string, data: any) => Promise<any>;
|
|
31
36
|
apiFilterList: (collectionName: string, filter: string) => Promise<any>;
|
|
37
|
+
apiGetDataSourceCount: () => Promise<any>;
|
|
38
|
+
apiCreateRecordTriggerActionEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
39
|
+
apiApplyApprovalEvent: (data: any) => Promise<any>;
|
|
40
|
+
userLogin: (page: Page, approvalUserEmail: string, approvalUser: string) => Promise<Page>;
|
|
32
41
|
};
|
|
33
42
|
export default _default;
|
package/dist/e2e/e2eUtils.js
CHANGED
|
@@ -17,11 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
var e2eUtils_exports = {};
|
|
19
19
|
__export(e2eUtils_exports, {
|
|
20
|
+
apiApplyApprovalEvent: () => apiApplyApprovalEvent,
|
|
21
|
+
apiCreateRecordTriggerActionEvent: () => apiCreateRecordTriggerActionEvent,
|
|
20
22
|
apiCreateRecordTriggerFormEvent: () => apiCreateRecordTriggerFormEvent,
|
|
21
23
|
apiCreateWorkflow: () => apiCreateWorkflow,
|
|
22
24
|
apiCreateWorkflowNode: () => apiCreateWorkflowNode,
|
|
23
25
|
apiDeleteWorkflow: () => apiDeleteWorkflow,
|
|
24
26
|
apiFilterList: () => apiFilterList,
|
|
27
|
+
apiGetDataSourceCount: () => apiGetDataSourceCount,
|
|
25
28
|
apiGetList: () => apiGetList,
|
|
26
29
|
apiGetRecord: () => apiGetRecord,
|
|
27
30
|
apiGetWorkflow: () => apiGetWorkflow,
|
|
@@ -32,7 +35,8 @@ __export(e2eUtils_exports, {
|
|
|
32
35
|
apiUpdateWorkflow: () => apiUpdateWorkflow,
|
|
33
36
|
apiUpdateWorkflowNode: () => apiUpdateWorkflowNode,
|
|
34
37
|
apiUpdateWorkflowTrigger: () => apiUpdateWorkflowTrigger,
|
|
35
|
-
default: () => e2eUtils_default
|
|
38
|
+
default: () => e2eUtils_default,
|
|
39
|
+
userLogin: () => userLogin
|
|
36
40
|
});
|
|
37
41
|
module.exports = __toCommonJS(e2eUtils_exports);
|
|
38
42
|
var import_e2e = require("@nocobase/test/e2e");
|
|
@@ -257,6 +261,50 @@ const apiSubmitRecordTriggerFormEvent = async (triggerWorkflows, data) => {
|
|
|
257
261
|
}
|
|
258
262
|
return await result.json();
|
|
259
263
|
};
|
|
264
|
+
const apiGetDataSourceCount = async () => {
|
|
265
|
+
const api = await import_e2e.request.newContext({
|
|
266
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE
|
|
267
|
+
});
|
|
268
|
+
const state = await api.storageState();
|
|
269
|
+
const headers = getHeaders(state);
|
|
270
|
+
const result = await api.get(`/api/dataSources:list?pageSize=50`, {
|
|
271
|
+
headers
|
|
272
|
+
});
|
|
273
|
+
if (!result.ok()) {
|
|
274
|
+
throw new Error(await result.text());
|
|
275
|
+
}
|
|
276
|
+
return (await result.json()).meta.count;
|
|
277
|
+
};
|
|
278
|
+
const apiCreateRecordTriggerActionEvent = async (collectionName, triggerWorkflows, data) => {
|
|
279
|
+
const api = await import_e2e.request.newContext({
|
|
280
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE
|
|
281
|
+
});
|
|
282
|
+
const state = await api.storageState();
|
|
283
|
+
const headers = getHeaders(state);
|
|
284
|
+
const result = await api.post(`/api/${collectionName}:create?triggerWorkflows=${triggerWorkflows}`, {
|
|
285
|
+
headers,
|
|
286
|
+
data
|
|
287
|
+
});
|
|
288
|
+
if (!result.ok()) {
|
|
289
|
+
throw new Error(await result.text());
|
|
290
|
+
}
|
|
291
|
+
return (await result.json()).data;
|
|
292
|
+
};
|
|
293
|
+
const apiApplyApprovalEvent = async (data) => {
|
|
294
|
+
const api = await import_e2e.request.newContext({
|
|
295
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE
|
|
296
|
+
});
|
|
297
|
+
const state = await api.storageState();
|
|
298
|
+
const headers = getHeaders(state);
|
|
299
|
+
const result = await api.post("/api/approvals:create", {
|
|
300
|
+
headers,
|
|
301
|
+
data
|
|
302
|
+
});
|
|
303
|
+
if (!result.ok()) {
|
|
304
|
+
throw new Error(await result.text());
|
|
305
|
+
}
|
|
306
|
+
return (await result.json()).data;
|
|
307
|
+
};
|
|
260
308
|
const getStorageItem = (key, storageState) => {
|
|
261
309
|
var _a, _b;
|
|
262
310
|
return (_b = (_a = storageState.origins.find((item) => item.origin === APP_BASE_URL)) == null ? void 0 : _a.localStorage.find((item) => item.name === key)) == null ? void 0 : _b.value;
|
|
@@ -298,6 +346,14 @@ function getHeaders(storageState) {
|
|
|
298
346
|
}
|
|
299
347
|
return headers;
|
|
300
348
|
}
|
|
349
|
+
const userLogin = async (page, approvalUserEmail, approvalUser) => {
|
|
350
|
+
await page.goto(`${process.env.APP_BASE_URL}/signin`);
|
|
351
|
+
await page.getByPlaceholder("Email").fill(approvalUserEmail);
|
|
352
|
+
await page.getByPlaceholder("Password").fill(approvalUser);
|
|
353
|
+
await page.getByRole("button", { name: "Sign in" }).click();
|
|
354
|
+
await page.waitForLoadState("networkidle");
|
|
355
|
+
return page;
|
|
356
|
+
};
|
|
301
357
|
var e2eUtils_default = module.exports = {
|
|
302
358
|
apiCreateWorkflow,
|
|
303
359
|
apiUpdateWorkflow,
|
|
@@ -313,15 +369,22 @@ var e2eUtils_default = module.exports = {
|
|
|
313
369
|
apiGetList,
|
|
314
370
|
apiCreateRecordTriggerFormEvent,
|
|
315
371
|
apiSubmitRecordTriggerFormEvent,
|
|
316
|
-
apiFilterList
|
|
372
|
+
apiFilterList,
|
|
373
|
+
apiGetDataSourceCount,
|
|
374
|
+
apiCreateRecordTriggerActionEvent,
|
|
375
|
+
apiApplyApprovalEvent,
|
|
376
|
+
userLogin
|
|
317
377
|
};
|
|
318
378
|
// Annotate the CommonJS export names for ESM import in node:
|
|
319
379
|
0 && (module.exports = {
|
|
380
|
+
apiApplyApprovalEvent,
|
|
381
|
+
apiCreateRecordTriggerActionEvent,
|
|
320
382
|
apiCreateRecordTriggerFormEvent,
|
|
321
383
|
apiCreateWorkflow,
|
|
322
384
|
apiCreateWorkflowNode,
|
|
323
385
|
apiDeleteWorkflow,
|
|
324
386
|
apiFilterList,
|
|
387
|
+
apiGetDataSourceCount,
|
|
325
388
|
apiGetList,
|
|
326
389
|
apiGetRecord,
|
|
327
390
|
apiGetWorkflow,
|
|
@@ -331,5 +394,6 @@ var e2eUtils_default = module.exports = {
|
|
|
331
394
|
apiUpdateRecord,
|
|
332
395
|
apiUpdateWorkflow,
|
|
333
396
|
apiUpdateWorkflowNode,
|
|
334
|
-
apiUpdateWorkflowTrigger
|
|
397
|
+
apiUpdateWorkflowTrigger,
|
|
398
|
+
userLogin
|
|
335
399
|
});
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
"@nocobase/client": "0.
|
|
3
|
-
"@nocobase/utils": "0.
|
|
2
|
+
"@nocobase/client": "0.21.0-alpha.2",
|
|
3
|
+
"@nocobase/utils": "0.21.0-alpha.2",
|
|
4
4
|
"lodash": "4.17.21",
|
|
5
|
-
"@nocobase/test": "0.
|
|
6
|
-
"@nocobase/server": "0.
|
|
7
|
-
"@nocobase/
|
|
5
|
+
"@nocobase/test": "0.21.0-alpha.2",
|
|
6
|
+
"@nocobase/server": "0.21.0-alpha.2",
|
|
7
|
+
"@nocobase/resourcer": "0.21.0-alpha.2",
|
|
8
|
+
"@nocobase/data-source-manager": "0.21.0-alpha.2",
|
|
9
|
+
"@nocobase/database": "0.21.0-alpha.2"
|
|
8
10
|
};
|
package/dist/server/index.js
CHANGED
|
@@ -38,6 +38,8 @@ var import_test = require("@nocobase/test");
|
|
|
38
38
|
var import_functions = __toESM(require("./functions"));
|
|
39
39
|
var import_triggers = __toESM(require("./triggers"));
|
|
40
40
|
var import_instructions = __toESM(require("./instructions"));
|
|
41
|
+
var import_data_source_manager = require("@nocobase/data-source-manager");
|
|
42
|
+
var import_utils = require("@nocobase/utils");
|
|
41
43
|
function sleep(ms) {
|
|
42
44
|
return new Promise((resolve) => {
|
|
43
45
|
setTimeout(resolve, ms);
|
|
@@ -52,7 +54,7 @@ async function getApp(options = {}) {
|
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
|
-
|
|
57
|
+
const app = await (0, import_test.createMockServer)({
|
|
56
58
|
...others,
|
|
57
59
|
plugins: [
|
|
58
60
|
[
|
|
@@ -68,6 +70,25 @@ async function getApp(options = {}) {
|
|
|
68
70
|
...plugins
|
|
69
71
|
]
|
|
70
72
|
});
|
|
73
|
+
await app.dataSourceManager.add(
|
|
74
|
+
new import_data_source_manager.SequelizeDataSource({
|
|
75
|
+
name: "another",
|
|
76
|
+
collectionManager: {
|
|
77
|
+
database: (0, import_test.mockDatabase)({
|
|
78
|
+
tablePrefix: `t${(0, import_utils.uid)(5)}`
|
|
79
|
+
})
|
|
80
|
+
},
|
|
81
|
+
resourceManager: {}
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
const another = app.dataSourceManager.dataSources.get("another");
|
|
85
|
+
const anotherDB = another.collectionManager.db;
|
|
86
|
+
await anotherDB.import({
|
|
87
|
+
directory: import_path.default.resolve(__dirname, "collections")
|
|
88
|
+
});
|
|
89
|
+
await anotherDB.sync();
|
|
90
|
+
another.acl.allow("*", "*");
|
|
91
|
+
return app;
|
|
71
92
|
}
|
|
72
93
|
class WorkflowTestPlugin extends import_server.Plugin {
|
|
73
94
|
async load() {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@nocobase/plugin-workflow-test",
|
|
3
3
|
"displayName": "Workflow: test kit",
|
|
4
4
|
"displayName.zh-CN": "工作流:测试工具包",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.21.0-alpha.2",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
7
7
|
"main": "dist/server/index.js",
|
|
8
8
|
"types": "./dist/server/index.d.ts",
|
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
"@nocobase/server": "0.x",
|
|
12
12
|
"@nocobase/test": "0.x"
|
|
13
13
|
},
|
|
14
|
-
"gitHead": "
|
|
14
|
+
"gitHead": "90628f2e2da846208fb2d7966ddb4e467d187ffb"
|
|
15
15
|
}
|
|
@@ -79,62 +79,102 @@ export class ApprovalTriggerNode {
|
|
|
79
79
|
nodeTitle: Locator;
|
|
80
80
|
nodeConfigure: Locator;
|
|
81
81
|
collectionDropDown: Locator;
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
dataBlocksInitiationRadio: Locator;
|
|
83
|
+
dataBlocksAndGlobalApprovalBlocksInitiationRadio: Locator;
|
|
84
|
+
allowedToBeWithdrawnCheckbox: Locator;
|
|
85
|
+
goToconfigureButton: Locator;
|
|
84
86
|
addBlockButton: Locator;
|
|
85
87
|
addApplyFormMenu: Locator;
|
|
86
88
|
configureFieldsButton: Locator;
|
|
87
89
|
configureActionsButton: Locator;
|
|
88
90
|
saveDraftSwitch: Locator;
|
|
91
|
+
submitButton: Locator;
|
|
92
|
+
cancelButton: Locator;
|
|
89
93
|
addNodeButton: Locator;
|
|
90
94
|
constructor(page: Page, triggerName: string, collectionName: string) {
|
|
91
95
|
this.page = page;
|
|
92
96
|
this.node = page.getByText('TriggeraConfigure');
|
|
93
97
|
this.nodeTitle = page.locator('textarea').filter({ hasText: triggerName });
|
|
94
98
|
this.nodeConfigure = page.getByRole('button', { name: 'Configure' });
|
|
95
|
-
this.collectionDropDown = page
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.
|
|
99
|
+
this.collectionDropDown = page
|
|
100
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
101
|
+
.locator('.ant-select-selection-search-input');
|
|
102
|
+
this.dataBlocksInitiationRadio = page.getByLabel('Initiate and approve in data blocks only');
|
|
103
|
+
this.dataBlocksAndGlobalApprovalBlocksInitiationRadio = page.getByLabel(
|
|
104
|
+
'Initiate and approve in both data blocks and global approval blocks',
|
|
105
|
+
);
|
|
106
|
+
this.allowedToBeWithdrawnCheckbox = page.getByLabel('Allowed to be withdrawn');
|
|
107
|
+
this.goToconfigureButton = page.getByRole('button', { name: 'Go to configure' });
|
|
108
|
+
this.addBlockButton = page.getByLabel(`schema-initializer-Grid-ApprovalApplyAddBlockButton-${collectionName}`);
|
|
99
109
|
this.addApplyFormMenu = page.getByRole('menuitem', { name: 'Apply form' });
|
|
100
|
-
this.configureFieldsButton = page.
|
|
101
|
-
this.configureActionsButton = page.
|
|
102
|
-
|
|
110
|
+
this.configureFieldsButton = page.getByLabel(`schema-initializer-Grid-form:configureFields-${collectionName}`);
|
|
111
|
+
this.configureActionsButton = page.getByLabel(
|
|
112
|
+
`schema-initializer-ActionBar-ApprovalApplyAddActionButton-${collectionName}`,
|
|
103
113
|
);
|
|
104
114
|
this.saveDraftSwitch = page.getByRole('menuitem', { name: 'Save draft' }).getByRole('switch');
|
|
105
|
-
this.
|
|
115
|
+
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
116
|
+
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
117
|
+
this.addNodeButton = this.addNodeButton = page.getByLabel('add-button', { exact: true });
|
|
106
118
|
}
|
|
107
119
|
}
|
|
108
120
|
|
|
109
|
-
export class
|
|
121
|
+
export class ApprovalPassthroughModeNode {
|
|
110
122
|
readonly page: Page;
|
|
111
123
|
node: Locator;
|
|
112
124
|
nodeTitle: Locator;
|
|
113
125
|
nodeConfigure: Locator;
|
|
126
|
+
addAssigneesButton: Locator;
|
|
114
127
|
assigneesDropDown: Locator;
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
OrRadio: Locator;
|
|
129
|
+
AndRadio: Locator;
|
|
130
|
+
votingRadio: Locator;
|
|
131
|
+
parallellyRadio: Locator;
|
|
132
|
+
sequentiallyRadio: Locator;
|
|
133
|
+
goToconfigureButton: Locator;
|
|
117
134
|
addBlockButton: Locator;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
addDetailsMenu: Locator;
|
|
136
|
+
detailsConfigureFieldsButton: Locator;
|
|
137
|
+
addActionsMenu: Locator;
|
|
138
|
+
actionsConfigureFieldsButton: Locator;
|
|
139
|
+
actionsConfigureActionsButton: Locator;
|
|
140
|
+
addApproveButton: Locator;
|
|
141
|
+
addRejectButton: Locator;
|
|
142
|
+
addReturnButton: Locator;
|
|
143
|
+
addNodeResult: Locator;
|
|
144
|
+
submitButton: Locator;
|
|
145
|
+
cancelButton: Locator;
|
|
122
146
|
addNodeButton: Locator;
|
|
123
147
|
constructor(page: Page, nodeName: string, collectionName: string) {
|
|
124
148
|
this.page = page;
|
|
125
|
-
this.node = page.
|
|
126
|
-
this.nodeTitle = page.
|
|
127
|
-
this.nodeConfigure = page
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.
|
|
131
|
-
this.
|
|
132
|
-
this.
|
|
133
|
-
this.
|
|
134
|
-
this.
|
|
135
|
-
|
|
149
|
+
this.node = page.getByLabel(`Approval-${nodeName}`, { exact: true });
|
|
150
|
+
this.nodeTitle = page.getByLabel(`Approval-${nodeName}`, { exact: true }).getByRole('textbox');
|
|
151
|
+
this.nodeConfigure = page
|
|
152
|
+
.getByLabel(`Approval-${nodeName}`, { exact: true })
|
|
153
|
+
.getByRole('button', { name: 'Configure' });
|
|
154
|
+
this.addAssigneesButton = page.getByRole('button', { name: 'plus Add assignee' });
|
|
155
|
+
this.assigneesDropDown = page.getByTestId('select-single');
|
|
156
|
+
this.OrRadio = page.getByLabel('Or', { exact: true });
|
|
157
|
+
this.AndRadio = page.getByLabel('And', { exact: true });
|
|
158
|
+
this.votingRadio = page.getByLabel('Voting', { exact: true });
|
|
159
|
+
this.parallellyRadio = page.getByLabel('Parallelly', { exact: true });
|
|
160
|
+
this.sequentiallyRadio = page.getByLabel('Sequentially', { exact: true });
|
|
161
|
+
this.goToconfigureButton = page.getByRole('button', { name: 'Go to configure' });
|
|
162
|
+
this.addBlockButton = page.getByLabel('schema-initializer-Grid-ApprovalProcessAddBlockButton-workflows');
|
|
163
|
+
this.addDetailsMenu = page.getByRole('menuitem', { name: 'Details' });
|
|
164
|
+
this.detailsConfigureFieldsButton = page.getByLabel(
|
|
165
|
+
`schema-initializer-Grid-ReadPrettyFormItemInitializers-${collectionName}`,
|
|
136
166
|
);
|
|
137
|
-
this.
|
|
167
|
+
this.addActionsMenu = page.getByRole('menuitem', { name: 'Actions' }).getByRole('switch');
|
|
168
|
+
this.actionsConfigureFieldsButton = page.getByLabel('schema-initializer-Grid-FormItemInitializers-approvalRecords');
|
|
169
|
+
this.actionsConfigureActionsButton = page.getByLabel(
|
|
170
|
+
'schema-initializer-ActionBar-ApprovalProcessAddActionButton-approvalRecords',
|
|
171
|
+
);
|
|
172
|
+
this.addApproveButton = page.getByRole('menuitem', { name: 'Approve' }).getByRole('switch');
|
|
173
|
+
this.addRejectButton = page.getByRole('menuitem', { name: 'Reject' }).getByRole('switch');
|
|
174
|
+
this.addReturnButton = page.getByRole('menuitem', { name: 'Return' }).getByRole('switch');
|
|
175
|
+
this.addNodeResult = page.getByRole('menuitem', { name: 'Node result right' });
|
|
176
|
+
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
177
|
+
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
138
178
|
this.addNodeButton = page.getByLabel(`add-button-calculation-${nodeName}`, { exact: true });
|
|
139
179
|
}
|
|
140
180
|
}
|
|
@@ -164,7 +204,9 @@ export class ScheduleTriggerNode {
|
|
|
164
204
|
this.RrpeatModeDropdown = page.getByLabel('block-item-RepeatField-workflows-Repeat mode');
|
|
165
205
|
|
|
166
206
|
this.dataTableTimeFieldOptions = page.getByLabel('Based on date field of collection');
|
|
167
|
-
this.collectionDropDown = page
|
|
207
|
+
this.collectionDropDown = page
|
|
208
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
209
|
+
.locator('.ant-select-selection-search-input');
|
|
168
210
|
this.startTimeDropdown = page.getByLabel('block-item-OnField-workflows-Starts on');
|
|
169
211
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
170
212
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
@@ -187,7 +229,10 @@ export class CollectionTriggerNode {
|
|
|
187
229
|
this.node = page.getByLabel(`Trigger-${triggerName}`);
|
|
188
230
|
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
|
|
189
231
|
this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
|
|
190
|
-
this.collectionDropDown = page.getByRole('button', { name: 'Select collection' });
|
|
232
|
+
// this.collectionDropDown = page.getByRole('button', { name: 'Select collection' });
|
|
233
|
+
this.collectionDropDown = page
|
|
234
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
235
|
+
.locator('.ant-select-selection-search-input');
|
|
191
236
|
this.triggerOnDropdown = page
|
|
192
237
|
.getByLabel('block-item-Select-workflows-Trigger on')
|
|
193
238
|
.getByRole('button', { name: 'Trigger on' });
|
|
@@ -212,7 +257,9 @@ export class FormEventTriggerNode {
|
|
|
212
257
|
this.node = page.getByLabel(`Trigger-${triggerName}`);
|
|
213
258
|
this.nodeTitle = page.getByLabel(`Trigger-${triggerName}`).getByRole('textbox');
|
|
214
259
|
this.nodeConfigure = page.getByLabel(`Trigger-${triggerName}`).getByRole('button', { name: 'Configure' });
|
|
215
|
-
this.collectionDropDown = page
|
|
260
|
+
this.collectionDropDown = page
|
|
261
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
262
|
+
.locator('.ant-select-selection-search-input');
|
|
216
263
|
this.relationalDataDropdown = page.getByTestId('select-field-Preload associations');
|
|
217
264
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
218
265
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
@@ -269,7 +316,9 @@ export class QueryRecordNode {
|
|
|
269
316
|
this.nodeConfigure = page
|
|
270
317
|
.getByLabel(`Query record-${nodeName}`, { exact: true })
|
|
271
318
|
.getByRole('button', { name: 'Configure' });
|
|
272
|
-
this.collectionDropDown = page
|
|
319
|
+
this.collectionDropDown = page
|
|
320
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
321
|
+
.locator('.ant-select-selection-search-input');
|
|
273
322
|
this.allowMultipleDataBoxesForResults = page.getByLabel('Allow multiple records as');
|
|
274
323
|
this.addSortFieldsButton = page.getByRole('button', { name: 'plus Add sort field' });
|
|
275
324
|
this.pageNumberEditBox = page.getByLabel('variable-constant');
|
|
@@ -299,7 +348,9 @@ export class CreateRecordNode {
|
|
|
299
348
|
this.nodeConfigure = page
|
|
300
349
|
.getByLabel(`Create record-${nodeName}`, { exact: true })
|
|
301
350
|
.getByRole('button', { name: 'Configure' });
|
|
302
|
-
this.collectionDropDown = page
|
|
351
|
+
this.collectionDropDown = page
|
|
352
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
353
|
+
.locator('.ant-select-selection-search-input');
|
|
303
354
|
this.addFieldsButton = page.getByRole('button', { name: 'plus Add field' });
|
|
304
355
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
305
356
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
@@ -326,7 +377,9 @@ export class UpdateRecordNode {
|
|
|
326
377
|
this.nodeConfigure = page
|
|
327
378
|
.getByLabel(`Update record-${nodeName}`, { exact: true })
|
|
328
379
|
.getByRole('button', { name: 'Configure' });
|
|
329
|
-
this.collectionDropDown = page
|
|
380
|
+
this.collectionDropDown = page
|
|
381
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
382
|
+
.locator('.ant-select-selection-search-input');
|
|
330
383
|
this.batchUpdateModeRadio = page
|
|
331
384
|
.getByLabel('block-item-IndividualHooksRadioWithTooltip-workflows-Update mode')
|
|
332
385
|
.getByLabel('Update in a batch');
|
|
@@ -356,7 +409,9 @@ export class DeleteRecordNode {
|
|
|
356
409
|
this.nodeConfigure = page
|
|
357
410
|
.getByLabel(`Delete record-${nodeName}`, { exact: true })
|
|
358
411
|
.getByRole('button', { name: 'Configure' });
|
|
359
|
-
this.collectionDropDown = page
|
|
412
|
+
this.collectionDropDown = page
|
|
413
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Collection')
|
|
414
|
+
.locator('.ant-select-selection-search-input');
|
|
360
415
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
361
416
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
362
417
|
this.addNodeButton = page.getByLabel(`add-button-delete-${nodeName}`, { exact: true });
|
|
@@ -395,11 +450,12 @@ export class AggregateNode {
|
|
|
395
450
|
this.minRadio = page.getByLabel('MIN', { exact: true });
|
|
396
451
|
this.dataTableDataRadio = page.getByLabel('Data of collection');
|
|
397
452
|
this.linkedDataTableDataRadio = page.getByLabel('Data of associated collection');
|
|
398
|
-
this.collectionDropDown = page
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
453
|
+
this.collectionDropDown = page
|
|
454
|
+
.getByLabel('block-item-DataSourceCollectionCascader-workflows-Data of collection')
|
|
455
|
+
.locator('.ant-select-selection-search-input');
|
|
456
|
+
this.aggregatedFieldDropDown = page
|
|
457
|
+
.getByLabel('block-item-FieldsSelect-workflows-Field to aggregate')
|
|
458
|
+
.locator('.ant-select-selection-search-input');
|
|
403
459
|
this.distinctCheckBox = page
|
|
404
460
|
.getByLabel('block-item-Checkbox-workflows-Distinct')
|
|
405
461
|
.locator('input.ant-checkbox-input[type="checkbox"]');
|
|
@@ -434,7 +490,9 @@ export class ManualNode {
|
|
|
434
490
|
.getByRole('button', { name: 'Configure' });
|
|
435
491
|
this.assigneesDropDown = page.getByTestId('select-single');
|
|
436
492
|
this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' });
|
|
437
|
-
this.addBlockButton = page.getByLabel(
|
|
493
|
+
this.addBlockButton = page.getByLabel(
|
|
494
|
+
'schema-initializer-Grid-workflowManual:popup:configureUserInterface:addBlock-workflows',
|
|
495
|
+
);
|
|
438
496
|
this.triggerDataMenu = page.getByRole('menuitem', { name: 'Trigger data' });
|
|
439
497
|
this.nodeDataMenu = page.getByRole('menuitem', { name: 'Node result right' });
|
|
440
498
|
this.customFormMenu = page.getByRole('menuitem', { name: 'Custom form' });
|
|
@@ -570,7 +628,7 @@ export default module.exports = {
|
|
|
570
628
|
WorkflowManagement,
|
|
571
629
|
WorkflowListRecords,
|
|
572
630
|
ApprovalTriggerNode,
|
|
573
|
-
|
|
631
|
+
ApprovalPassthroughModeNode,
|
|
574
632
|
ScheduleTriggerNode,
|
|
575
633
|
CollectionTriggerNode,
|
|
576
634
|
FormEventTriggerNode,
|
package/src/e2e/e2eUtils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { request } from '@nocobase/test/e2e';
|
|
1
|
+
import { request, Page } from '@nocobase/test/e2e';
|
|
2
2
|
|
|
3
3
|
const PORT = process.env.APP_PORT || 20000;
|
|
4
4
|
const APP_BASE_URL = process.env.APP_BASE_URL || `http://localhost:${PORT}`;
|
|
@@ -722,6 +722,156 @@ export const apiSubmitRecordTriggerFormEvent = async (triggerWorkflows: string,
|
|
|
722
722
|
return await result.json();
|
|
723
723
|
};
|
|
724
724
|
|
|
725
|
+
// 获取数据源个数
|
|
726
|
+
export const apiGetDataSourceCount = async () => {
|
|
727
|
+
const api = await request.newContext({
|
|
728
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
|
729
|
+
});
|
|
730
|
+
const state = await api.storageState();
|
|
731
|
+
const headers = getHeaders(state);
|
|
732
|
+
const result = await api.get(`/api/dataSources:list?pageSize=50`, {
|
|
733
|
+
headers,
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
if (!result.ok()) {
|
|
737
|
+
throw new Error(await result.text());
|
|
738
|
+
}
|
|
739
|
+
/*
|
|
740
|
+
{
|
|
741
|
+
"data": 1
|
|
742
|
+
}
|
|
743
|
+
*/
|
|
744
|
+
return (await result.json()).meta.count;
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
// 添加业务表单条数据触发工作流表单事件,triggerWorkflows=key1!field,key2,key3!field.subfield
|
|
748
|
+
export const apiCreateRecordTriggerActionEvent = async (
|
|
749
|
+
collectionName: string,
|
|
750
|
+
triggerWorkflows: string,
|
|
751
|
+
data: any,
|
|
752
|
+
) => {
|
|
753
|
+
const api = await request.newContext({
|
|
754
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
|
755
|
+
});
|
|
756
|
+
const state = await api.storageState();
|
|
757
|
+
const headers = getHeaders(state);
|
|
758
|
+
/*
|
|
759
|
+
{
|
|
760
|
+
"title": "a11",
|
|
761
|
+
"enabled": true,
|
|
762
|
+
"description": null
|
|
763
|
+
}
|
|
764
|
+
*/
|
|
765
|
+
const result = await api.post(`/api/${collectionName}:create?triggerWorkflows=${triggerWorkflows}`, {
|
|
766
|
+
headers,
|
|
767
|
+
data,
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
if (!result.ok()) {
|
|
771
|
+
throw new Error(await result.text());
|
|
772
|
+
}
|
|
773
|
+
/*
|
|
774
|
+
{
|
|
775
|
+
"data": {
|
|
776
|
+
"id": 1,
|
|
777
|
+
"createdAt": "2023-12-12T02:43:53.793Z",
|
|
778
|
+
"updatedAt": "2023-12-12T05:41:33.300Z",
|
|
779
|
+
"key": "fzk3j2oj4el",
|
|
780
|
+
"title": "a11",
|
|
781
|
+
"enabled": true,
|
|
782
|
+
"description": null
|
|
783
|
+
},
|
|
784
|
+
"meta": {
|
|
785
|
+
"allowedActions": {
|
|
786
|
+
"view": [
|
|
787
|
+
1
|
|
788
|
+
],
|
|
789
|
+
"update": [
|
|
790
|
+
1
|
|
791
|
+
],
|
|
792
|
+
"destroy": [
|
|
793
|
+
1
|
|
794
|
+
]
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
*/
|
|
799
|
+
return (await result.json()).data;
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
// 审批中心发起审批
|
|
803
|
+
export const apiApplyApprovalEvent = async (data: any) => {
|
|
804
|
+
const api = await request.newContext({
|
|
805
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
|
806
|
+
});
|
|
807
|
+
const state = await api.storageState();
|
|
808
|
+
const headers = getHeaders(state);
|
|
809
|
+
/*
|
|
810
|
+
{
|
|
811
|
+
"title": "a11",
|
|
812
|
+
"enabled": true,
|
|
813
|
+
"description": null
|
|
814
|
+
}
|
|
815
|
+
*/
|
|
816
|
+
const result = await api.post('/api/approvals:create', {
|
|
817
|
+
headers,
|
|
818
|
+
data,
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
if (!result.ok()) {
|
|
822
|
+
throw new Error(await result.text());
|
|
823
|
+
}
|
|
824
|
+
/*
|
|
825
|
+
{
|
|
826
|
+
"data": {
|
|
827
|
+
"id": 35,
|
|
828
|
+
"collectionName": "tt_amt_orgREmwr",
|
|
829
|
+
"data": {
|
|
830
|
+
"id": 6,
|
|
831
|
+
"url": null,
|
|
832
|
+
"sort": 3,
|
|
833
|
+
"email": null,
|
|
834
|
+
"phone": null,
|
|
835
|
+
"address": null,
|
|
836
|
+
"orgcode": "区域编码000000006",
|
|
837
|
+
"orgname": "阿三大苏打实打实的",
|
|
838
|
+
"isenable": null,
|
|
839
|
+
"staffnum": null,
|
|
840
|
+
"createdAt": "2024-03-09T11:37:47.620Z",
|
|
841
|
+
"sharesnum": null,
|
|
842
|
+
"updatedAt": "2024-03-09T11:37:47.620Z",
|
|
843
|
+
"insurednum": null,
|
|
844
|
+
"range_json": null,
|
|
845
|
+
"regcapital": null,
|
|
846
|
+
"testdataid": null,
|
|
847
|
+
"createdById": 1,
|
|
848
|
+
"paidcapital": null,
|
|
849
|
+
"range_check": [],
|
|
850
|
+
"updatedById": 1,
|
|
851
|
+
"status_radio": null,
|
|
852
|
+
"establishdate": null,
|
|
853
|
+
"insuranceratio": null,
|
|
854
|
+
"range_markdown": null,
|
|
855
|
+
"range_richtext": null,
|
|
856
|
+
"status_singleselect": null,
|
|
857
|
+
"range_multipleselect": [],
|
|
858
|
+
"insuranceratio_formula": null
|
|
859
|
+
},
|
|
860
|
+
"status": 2,
|
|
861
|
+
"workflowId": 39,
|
|
862
|
+
"dataKey": "6",
|
|
863
|
+
"updatedAt": "2024-03-09T11:37:47.640Z",
|
|
864
|
+
"createdAt": "2024-03-09T11:37:47.640Z",
|
|
865
|
+
"createdById": 1,
|
|
866
|
+
"updatedById": 1,
|
|
867
|
+
"workflowKey": null,
|
|
868
|
+
"latestExecutionId": null
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
*/
|
|
872
|
+
return (await result.json()).data;
|
|
873
|
+
};
|
|
874
|
+
|
|
725
875
|
const getStorageItem = (key: string, storageState: any) => {
|
|
726
876
|
return storageState.origins
|
|
727
877
|
.find((item) => item.origin === APP_BASE_URL)
|
|
@@ -767,6 +917,16 @@ function getHeaders(storageState: any) {
|
|
|
767
917
|
return headers;
|
|
768
918
|
}
|
|
769
919
|
|
|
920
|
+
// 用户登录新会话
|
|
921
|
+
export const userLogin = async (page: Page, approvalUserEmail: string, approvalUser: string) => {
|
|
922
|
+
await page.goto(`${process.env.APP_BASE_URL}/signin`);
|
|
923
|
+
await page.getByPlaceholder('Email').fill(approvalUserEmail);
|
|
924
|
+
await page.getByPlaceholder('Password').fill(approvalUser);
|
|
925
|
+
await page.getByRole('button', { name: 'Sign in' }).click();
|
|
926
|
+
await page.waitForLoadState('networkidle');
|
|
927
|
+
return page;
|
|
928
|
+
};
|
|
929
|
+
|
|
770
930
|
export default module.exports = {
|
|
771
931
|
apiCreateWorkflow,
|
|
772
932
|
apiUpdateWorkflow,
|
|
@@ -783,4 +943,8 @@ export default module.exports = {
|
|
|
783
943
|
apiCreateRecordTriggerFormEvent,
|
|
784
944
|
apiSubmitRecordTriggerFormEvent,
|
|
785
945
|
apiFilterList,
|
|
946
|
+
apiGetDataSourceCount,
|
|
947
|
+
apiCreateRecordTriggerActionEvent,
|
|
948
|
+
apiApplyApprovalEvent,
|
|
949
|
+
userLogin,
|
|
786
950
|
};
|
package/src/server/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
|
|
3
3
|
import { ApplicationOptions, Plugin } from '@nocobase/server';
|
|
4
|
-
import { MockServer, createMockServer } from '@nocobase/test';
|
|
4
|
+
import { MockServer, createMockServer, mockDatabase } from '@nocobase/test';
|
|
5
5
|
|
|
6
6
|
import functions from './functions';
|
|
7
7
|
import triggers from './triggers';
|
|
8
8
|
import instructions from './instructions';
|
|
9
|
+
import { Resourcer } from '@nocobase/resourcer';
|
|
10
|
+
import { SequelizeDataSource } from '@nocobase/data-source-manager';
|
|
11
|
+
import { uid } from '@nocobase/utils';
|
|
9
12
|
|
|
10
13
|
export interface MockServerOptions extends ApplicationOptions {
|
|
11
14
|
collectionsPath?: string;
|
|
@@ -33,7 +36,7 @@ export async function getApp(options: MockServerOptions = {}): Promise<MockServe
|
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
|
-
|
|
39
|
+
const app = await createMockServer({
|
|
37
40
|
...others,
|
|
38
41
|
plugins: [
|
|
39
42
|
[
|
|
@@ -49,6 +52,30 @@ export async function getApp(options: MockServerOptions = {}): Promise<MockServe
|
|
|
49
52
|
...plugins,
|
|
50
53
|
],
|
|
51
54
|
});
|
|
55
|
+
|
|
56
|
+
await app.dataSourceManager.add(
|
|
57
|
+
new SequelizeDataSource({
|
|
58
|
+
name: 'another',
|
|
59
|
+
collectionManager: {
|
|
60
|
+
database: mockDatabase({
|
|
61
|
+
tablePrefix: `t${uid(5)}`,
|
|
62
|
+
}),
|
|
63
|
+
},
|
|
64
|
+
resourceManager: {},
|
|
65
|
+
}),
|
|
66
|
+
);
|
|
67
|
+
const another = app.dataSourceManager.dataSources.get('another');
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
const anotherDB = another.collectionManager.db;
|
|
70
|
+
|
|
71
|
+
await anotherDB.import({
|
|
72
|
+
directory: path.resolve(__dirname, 'collections'),
|
|
73
|
+
});
|
|
74
|
+
await anotherDB.sync();
|
|
75
|
+
|
|
76
|
+
another.acl.allow('*', '*');
|
|
77
|
+
|
|
78
|
+
return app;
|
|
52
79
|
}
|
|
53
80
|
|
|
54
81
|
export default class WorkflowTestPlugin extends Plugin {
|