@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.
@@ -42,29 +42,45 @@ export declare class ApprovalTriggerNode {
42
42
  nodeTitle: Locator;
43
43
  nodeConfigure: Locator;
44
44
  collectionDropDown: Locator;
45
- checkWthdrawable: Locator;
46
- configureUserInterfaceButton: Locator;
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 ApprovalNode {
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
- checkReturnable: Locator;
62
- configureUserInterfaceButton: Locator;
66
+ OrRadio: Locator;
67
+ AndRadio: Locator;
68
+ votingRadio: Locator;
69
+ parallellyRadio: Locator;
70
+ sequentiallyRadio: Locator;
71
+ goToconfigureButton: Locator;
63
72
  addBlockButton: Locator;
64
- addApplyFormMenu: Locator;
65
- configureFieldsButton: Locator;
66
- configureActionsButton: Locator;
67
- saveDraftSwitch: Locator;
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
- ApprovalNode: typeof ApprovalNode;
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
- ApprovalNode: () => ApprovalNode,
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
- checkWthdrawable;
116
- configureUserInterfaceButton;
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.getByRole("button", { name: "Select collection" });
129
- this.checkWthdrawable = page.getByLabel("Withdrawable");
130
- this.configureUserInterfaceButton = page.getByRole("button", { name: "Configure user interface" });
131
- this.addBlockButton = page.getByRole("button", { name: "Add block" });
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.getByTestId("configure-fields-button-of-form-item-" + collectionName);
134
- this.configureActionsButton = page.getByTestId(
135
- "approval-trigger-configure-form-actions-add-action-button-" + collectionName
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.addNodeButton = page.getByLabel("add-button", { exact: true });
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 ApprovalNode {
151
+ class ApprovalPassthroughModeNode {
142
152
  page;
143
153
  node;
144
154
  nodeTitle;
145
155
  nodeConfigure;
156
+ addAssigneesButton;
146
157
  assigneesDropDown;
147
- checkReturnable;
148
- configureUserInterfaceButton;
158
+ OrRadio;
159
+ AndRadio;
160
+ votingRadio;
161
+ parallellyRadio;
162
+ sequentiallyRadio;
163
+ goToconfigureButton;
149
164
  addBlockButton;
150
- addApplyFormMenu;
151
- configureFieldsButton;
152
- configureActionsButton;
153
- saveDraftSwitch;
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.getByText("TriggeraConfigure");
158
- this.nodeTitle = page.locator("textarea").filter({ hasText: nodeName });
159
- this.nodeConfigure = page.getByRole("button", { name: "Configure" });
160
- this.assigneesDropDown = page.getByLabel("Search");
161
- this.checkReturnable = page.getByLabel("Returnable");
162
- this.configureUserInterfaceButton = page.getByRole("button", { name: "Configure user interface" });
163
- this.addBlockButton = page.getByTestId("add-block-button-in-workflow-workflows");
164
- this.addApplyFormMenu = page.getByRole("menuitem", { name: "Apply form" });
165
- this.configureFieldsButton = page.getByTestId("configure-fields-button-of-form-item-" + collectionName);
166
- this.configureActionsButton = page.getByTestId(
167
- "approval-trigger-configure-form-actions-add-action-button-" + collectionName
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.saveDraftSwitch = page.getByRole("menuitem", { name: "Save draft" }).getByRole("switch");
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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.getByRole("button", { name: "Select collection" });
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("schema-initializer-Grid-AddBlockButton-workflows");
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
- ApprovalNode,
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
- ApprovalNode,
608
+ ApprovalPassthroughModeNode,
573
609
  ApprovalTriggerNode,
574
610
  ClculationNode,
575
611
  CollectionTriggerNode,
@@ -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;
@@ -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
  });
@@ -1,8 +1,10 @@
1
1
  module.exports = {
2
- "@nocobase/client": "0.20.0-alpha.9",
3
- "@nocobase/utils": "0.20.0-alpha.9",
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.20.0-alpha.9",
6
- "@nocobase/server": "0.20.0-alpha.9",
7
- "@nocobase/database": "0.20.0-alpha.9"
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
  };
@@ -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
- return (0, import_test.createMockServer)({
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.20.0-alpha.9",
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": "5473d9039cfdb649a8c8c625edefc9a3ac464be5"
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
- checkWthdrawable: Locator;
83
- configureUserInterfaceButton: Locator;
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.getByRole('button', { name: 'Select collection' });
96
- this.checkWthdrawable = page.getByLabel('Withdrawable');
97
- this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' });
98
- this.addBlockButton = page.getByRole('button', { name: 'Add block' });
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.getByTestId('configure-fields-button-of-form-item-' + collectionName);
101
- this.configureActionsButton = page.getByTestId(
102
- 'approval-trigger-configure-form-actions-add-action-button-' + collectionName,
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.addNodeButton = page.getByLabel('add-button', { exact: true });
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 ApprovalNode {
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
- checkReturnable: Locator;
116
- configureUserInterfaceButton: Locator;
128
+ OrRadio: Locator;
129
+ AndRadio: Locator;
130
+ votingRadio: Locator;
131
+ parallellyRadio: Locator;
132
+ sequentiallyRadio: Locator;
133
+ goToconfigureButton: Locator;
117
134
  addBlockButton: Locator;
118
- addApplyFormMenu: Locator;
119
- configureFieldsButton: Locator;
120
- configureActionsButton: Locator;
121
- saveDraftSwitch: Locator;
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.getByText('TriggeraConfigure');
126
- this.nodeTitle = page.locator('textarea').filter({ hasText: nodeName });
127
- this.nodeConfigure = page.getByRole('button', { name: 'Configure' });
128
- this.assigneesDropDown = page.getByLabel('Search');
129
- this.checkReturnable = page.getByLabel('Returnable');
130
- this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' });
131
- this.addBlockButton = page.getByTestId('add-block-button-in-workflow-workflows');
132
- this.addApplyFormMenu = page.getByRole('menuitem', { name: 'Apply form' });
133
- this.configureFieldsButton = page.getByTestId('configure-fields-button-of-form-item-' + collectionName);
134
- this.configureActionsButton = page.getByTestId(
135
- 'approval-trigger-configure-form-actions-add-action-button-' + collectionName,
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.saveDraftSwitch = page.getByRole('menuitem', { name: 'Save draft' }).getByRole('switch');
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
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.getByRole('button', { name: 'Select collection' });
399
- // this.aggregatedFieldDropDown = page.getByLabel('block-item-FieldsSelect-workflows-Field to aggregate').getByRole('textbox').getByRole('combobox');
400
- this.aggregatedFieldDropDown = page.locator(
401
- 'input.ant-select-selection-search-input[role="combobox"][aria-haspopup="listbox"]',
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('schema-initializer-Grid-AddBlockButton-workflows');
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
- ApprovalNode,
631
+ ApprovalPassthroughModeNode,
574
632
  ScheduleTriggerNode,
575
633
  CollectionTriggerNode,
576
634
  FormEventTriggerNode,
@@ -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
  };
@@ -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
- return createMockServer({
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 {