@nocobase/plugin-workflow-test 0.18.0-alpha.9 → 0.19.0-alpha.10
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 +30 -0
- package/dist/e2e/e2ePageObjectModel.js +63 -5
- package/dist/e2e/e2eUtils.d.ts +2 -0
- package/dist/e2e/e2eUtils.js +18 -1
- package/dist/externalVersion.js +5 -5
- package/dist/server/index.d.ts +3 -6
- package/dist/server/index.js +17 -34
- package/dist/server/instructions.d.ts +1 -1
- package/dist/server/instructions.js +0 -1
- package/dist/server/triggers.d.ts +20 -0
- package/dist/server/triggers.js +49 -0
- package/package.json +2 -2
- package/src/e2e/e2ePageObjectModel.ts +64 -4
- package/src/e2e/e2eUtils.ts +39 -0
- package/src/server/index.ts +25 -45
- package/src/server/instructions.ts +0 -1
- package/src/server/triggers.ts +19 -0
|
@@ -189,6 +189,7 @@ export declare class AggregateNode {
|
|
|
189
189
|
linkedDataTableDataRadio: Locator;
|
|
190
190
|
collectionDropDown: Locator;
|
|
191
191
|
aggregatedFieldDropDown: Locator;
|
|
192
|
+
distinctCheckBox: Locator;
|
|
192
193
|
submitButton: Locator;
|
|
193
194
|
cancelButton: Locator;
|
|
194
195
|
addNodeButton: Locator;
|
|
@@ -220,6 +221,7 @@ export declare class ConditionYesNode {
|
|
|
220
221
|
basicRadio: Locator;
|
|
221
222
|
mathRadio: Locator;
|
|
222
223
|
formulaRadio: Locator;
|
|
224
|
+
conditionExpressionEditBox: Locator;
|
|
223
225
|
submitButton: Locator;
|
|
224
226
|
cancelButton: Locator;
|
|
225
227
|
addNodeButton: Locator;
|
|
@@ -233,6 +235,7 @@ export declare class ConditionBranchNode {
|
|
|
233
235
|
basicRadio: Locator;
|
|
234
236
|
mathRadio: Locator;
|
|
235
237
|
formulaRadio: Locator;
|
|
238
|
+
conditionExpressionEditBox: Locator;
|
|
236
239
|
submitButton: Locator;
|
|
237
240
|
cancelButton: Locator;
|
|
238
241
|
addNoBranchNode: Locator;
|
|
@@ -240,6 +243,31 @@ export declare class ConditionBranchNode {
|
|
|
240
243
|
addNodeButton: Locator;
|
|
241
244
|
constructor(page: Page, nodeName: string);
|
|
242
245
|
}
|
|
246
|
+
export declare class SQLNode {
|
|
247
|
+
readonly page: Page;
|
|
248
|
+
node: Locator;
|
|
249
|
+
nodeTitle: Locator;
|
|
250
|
+
nodeConfigure: Locator;
|
|
251
|
+
sqlEditBox: Locator;
|
|
252
|
+
submitButton: Locator;
|
|
253
|
+
cancelButton: Locator;
|
|
254
|
+
addNodeButton: Locator;
|
|
255
|
+
constructor(page: Page, nodeName: string);
|
|
256
|
+
}
|
|
257
|
+
export declare class ParallelBranchNode {
|
|
258
|
+
readonly page: Page;
|
|
259
|
+
node: Locator;
|
|
260
|
+
nodeTitle: Locator;
|
|
261
|
+
nodeConfigure: Locator;
|
|
262
|
+
addBranchButton: Locator;
|
|
263
|
+
allSucceededRadio: Locator;
|
|
264
|
+
anySucceededRadio: Locator;
|
|
265
|
+
anySucceededOrFailedRadio: Locator;
|
|
266
|
+
submitButton: Locator;
|
|
267
|
+
cancelButton: Locator;
|
|
268
|
+
addNodeButton: Locator;
|
|
269
|
+
constructor(page: Page, nodeName: string);
|
|
270
|
+
}
|
|
243
271
|
declare const _default: {
|
|
244
272
|
CreateWorkFlow: typeof CreateWorkFlow;
|
|
245
273
|
EditWorkFlow: typeof EditWorkFlow;
|
|
@@ -259,5 +287,7 @@ declare const _default: {
|
|
|
259
287
|
ManualNode: typeof ManualNode;
|
|
260
288
|
ConditionYesNode: typeof ConditionYesNode;
|
|
261
289
|
ConditionBranchNode: typeof ConditionBranchNode;
|
|
290
|
+
SQLNode: typeof SQLNode;
|
|
291
|
+
ParallelBranchNode: typeof ParallelBranchNode;
|
|
262
292
|
};
|
|
263
293
|
export default _default;
|
|
@@ -30,7 +30,9 @@ __export(e2ePageObjectModel_exports, {
|
|
|
30
30
|
EditWorkFlow: () => EditWorkFlow,
|
|
31
31
|
FormEventTriggerNode: () => FormEventTriggerNode,
|
|
32
32
|
ManualNode: () => ManualNode,
|
|
33
|
+
ParallelBranchNode: () => ParallelBranchNode,
|
|
33
34
|
QueryRecordNode: () => QueryRecordNode,
|
|
35
|
+
SQLNode: () => SQLNode,
|
|
34
36
|
ScheduleTriggerNode: () => ScheduleTriggerNode,
|
|
35
37
|
UpdateRecordNode: () => UpdateRecordNode,
|
|
36
38
|
WorkflowListRecords: () => WorkflowListRecords,
|
|
@@ -380,6 +382,7 @@ class AggregateNode {
|
|
|
380
382
|
linkedDataTableDataRadio;
|
|
381
383
|
collectionDropDown;
|
|
382
384
|
aggregatedFieldDropDown;
|
|
385
|
+
distinctCheckBox;
|
|
383
386
|
submitButton;
|
|
384
387
|
cancelButton;
|
|
385
388
|
addNodeButton;
|
|
@@ -399,6 +402,7 @@ class AggregateNode {
|
|
|
399
402
|
this.aggregatedFieldDropDown = page.locator(
|
|
400
403
|
'input.ant-select-selection-search-input[role="combobox"][aria-haspopup="listbox"]'
|
|
401
404
|
);
|
|
405
|
+
this.distinctCheckBox = page.getByLabel("block-item-Checkbox-workflows-Distinct").locator('input.ant-checkbox-input[type="checkbox"]');
|
|
402
406
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
403
407
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
404
408
|
this.addNodeButton = page.getByLabel(`add-button-aggregate-${nodeName}`, { exact: true });
|
|
@@ -428,11 +432,11 @@ class ManualNode {
|
|
|
428
432
|
this.assigneesDropDown = page.getByTestId("select-single");
|
|
429
433
|
this.configureUserInterfaceButton = page.getByRole("button", { name: "Configure user interface" });
|
|
430
434
|
this.addBlockButton = page.getByLabel("schema-initializer-Grid-AddBlockButton-workflows");
|
|
431
|
-
this.triggerDataMenu = page.
|
|
432
|
-
this.nodeDataMenu = page.
|
|
435
|
+
this.triggerDataMenu = page.getByRole("menuitem", { name: "Trigger data" });
|
|
436
|
+
this.nodeDataMenu = page.getByRole("menuitem", { name: "Node result right" });
|
|
433
437
|
this.customFormMenu = page.getByRole("menuitem", { name: "Custom form" });
|
|
434
|
-
this.createRecordFormMenu = page.getByRole("menuitem", { name: "Create record form" });
|
|
435
|
-
this.updateRecordFormMenu = page.getByRole("menuitem", { name: "Update record form" });
|
|
438
|
+
this.createRecordFormMenu = page.getByRole("menuitem", { name: "Create record form right" });
|
|
439
|
+
this.updateRecordFormMenu = page.getByRole("menuitem", { name: "Update record form right" });
|
|
436
440
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
437
441
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
438
442
|
this.addNodeButton = page.getByLabel(`add-button-manual-${nodeName}`, { exact: true });
|
|
@@ -446,6 +450,7 @@ class ConditionYesNode {
|
|
|
446
450
|
basicRadio;
|
|
447
451
|
mathRadio;
|
|
448
452
|
formulaRadio;
|
|
453
|
+
conditionExpressionEditBox;
|
|
449
454
|
submitButton;
|
|
450
455
|
cancelButton;
|
|
451
456
|
addNodeButton;
|
|
@@ -454,6 +459,7 @@ class ConditionYesNode {
|
|
|
454
459
|
this.node = page.getByLabel(`Condition-${nodeName}`, { exact: true });
|
|
455
460
|
this.nodeTitle = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
456
461
|
this.nodeConfigure = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
462
|
+
this.conditionExpressionEditBox = page.getByLabel("textbox");
|
|
457
463
|
this.basicRadio = page.getByLabel("Basic");
|
|
458
464
|
this.mathRadio = page.getByLabel("Math.js");
|
|
459
465
|
this.formulaRadio = page.getByLabel("Formula.js");
|
|
@@ -470,6 +476,7 @@ class ConditionBranchNode {
|
|
|
470
476
|
basicRadio;
|
|
471
477
|
mathRadio;
|
|
472
478
|
formulaRadio;
|
|
479
|
+
conditionExpressionEditBox;
|
|
473
480
|
submitButton;
|
|
474
481
|
cancelButton;
|
|
475
482
|
addNoBranchNode;
|
|
@@ -480,6 +487,7 @@ class ConditionBranchNode {
|
|
|
480
487
|
this.node = page.getByLabel(`Condition-${nodeName}`, { exact: true });
|
|
481
488
|
this.nodeTitle = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
482
489
|
this.nodeConfigure = page.getByLabel(`Condition-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
490
|
+
this.conditionExpressionEditBox = page.getByLabel("textbox");
|
|
483
491
|
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
484
492
|
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
485
493
|
this.addNodeButton = page.getByLabel(`add-button-condition-${nodeName}`, { exact: true });
|
|
@@ -490,6 +498,52 @@ class ConditionBranchNode {
|
|
|
490
498
|
this.addYesBranchNode = page.getByLabel(`add-button-condition-${nodeName}-1`);
|
|
491
499
|
}
|
|
492
500
|
}
|
|
501
|
+
class SQLNode {
|
|
502
|
+
page;
|
|
503
|
+
node;
|
|
504
|
+
nodeTitle;
|
|
505
|
+
nodeConfigure;
|
|
506
|
+
sqlEditBox;
|
|
507
|
+
submitButton;
|
|
508
|
+
cancelButton;
|
|
509
|
+
addNodeButton;
|
|
510
|
+
constructor(page, nodeName) {
|
|
511
|
+
this.page = page;
|
|
512
|
+
this.node = page.getByLabel(`SQL action-${nodeName}`, { exact: true });
|
|
513
|
+
this.nodeTitle = page.getByLabel(`SQL action-${nodeName}`, { exact: true }).getByRole("textbox");
|
|
514
|
+
this.nodeConfigure = page.getByLabel(`SQL action-${nodeName}`, { exact: true }).getByRole("button", { name: "Configure" });
|
|
515
|
+
this.sqlEditBox = page.getByLabel("block-item-WorkflowVariableRawTextArea-workflows-SQL").getByRole("textbox");
|
|
516
|
+
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
517
|
+
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
518
|
+
this.addNodeButton = page.getByLabel(`add-button-sql-${nodeName}`, { exact: true });
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
class ParallelBranchNode {
|
|
522
|
+
page;
|
|
523
|
+
node;
|
|
524
|
+
nodeTitle;
|
|
525
|
+
nodeConfigure;
|
|
526
|
+
addBranchButton;
|
|
527
|
+
allSucceededRadio;
|
|
528
|
+
anySucceededRadio;
|
|
529
|
+
anySucceededOrFailedRadio;
|
|
530
|
+
submitButton;
|
|
531
|
+
cancelButton;
|
|
532
|
+
addNodeButton;
|
|
533
|
+
constructor(page, nodeName) {
|
|
534
|
+
this.page = page;
|
|
535
|
+
this.node = page.getByLabel(`Parallel branch-${nodeName}`, { exact: true });
|
|
536
|
+
this.nodeTitle = page.locator("textarea").filter({ hasText: nodeName });
|
|
537
|
+
this.nodeConfigure = page.getByLabel(`Parallel branch-${nodeName}`).getByRole("button", { name: "Configure" });
|
|
538
|
+
this.addBranchButton = page.getByLabel(`add-button-parallel-${nodeName}-add-branch`, { exact: true });
|
|
539
|
+
this.allSucceededRadio = page.getByLabel("All succeeded", { exact: true });
|
|
540
|
+
this.anySucceededRadio = page.getByLabel("Any succeeded", { exact: true });
|
|
541
|
+
this.anySucceededOrFailedRadio = page.getByLabel("Any succeeded or failed", { exact: true });
|
|
542
|
+
this.submitButton = page.getByLabel("action-Action-Submit-workflows");
|
|
543
|
+
this.cancelButton = page.getByLabel("action-Action-Cancel-workflows");
|
|
544
|
+
this.addNodeButton = page.getByLabel(`add-button-parallel-${nodeName}`, { exact: true });
|
|
545
|
+
}
|
|
546
|
+
}
|
|
493
547
|
var e2ePageObjectModel_default = module.exports = {
|
|
494
548
|
CreateWorkFlow,
|
|
495
549
|
EditWorkFlow,
|
|
@@ -508,7 +562,9 @@ var e2ePageObjectModel_default = module.exports = {
|
|
|
508
562
|
AggregateNode,
|
|
509
563
|
ManualNode,
|
|
510
564
|
ConditionYesNode,
|
|
511
|
-
ConditionBranchNode
|
|
565
|
+
ConditionBranchNode,
|
|
566
|
+
SQLNode,
|
|
567
|
+
ParallelBranchNode
|
|
512
568
|
};
|
|
513
569
|
// Annotate the CommonJS export names for ESM import in node:
|
|
514
570
|
0 && (module.exports = {
|
|
@@ -525,7 +581,9 @@ var e2ePageObjectModel_default = module.exports = {
|
|
|
525
581
|
EditWorkFlow,
|
|
526
582
|
FormEventTriggerNode,
|
|
527
583
|
ManualNode,
|
|
584
|
+
ParallelBranchNode,
|
|
528
585
|
QueryRecordNode,
|
|
586
|
+
SQLNode,
|
|
529
587
|
ScheduleTriggerNode,
|
|
530
588
|
UpdateRecordNode,
|
|
531
589
|
WorkflowListRecords,
|
package/dist/e2e/e2eUtils.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const apiGetWorkflowNodeExecutions: (id: number) => Promise<any>;
|
|
|
10
10
|
export declare const apiUpdateRecord: (collectionName: string, id: number, data: any) => Promise<any>;
|
|
11
11
|
export declare const apiGetRecord: (collectionName: string, id: number) => Promise<any>;
|
|
12
12
|
export declare const apiGetList: (collectionName: string) => Promise<any>;
|
|
13
|
+
export declare const apiFilterList: (collectionName: string, filter: string) => Promise<any>;
|
|
13
14
|
export declare const apiCreateRecordTriggerFormEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
14
15
|
export declare const apiSubmitRecordTriggerFormEvent: (triggerWorkflows: string, data: any) => Promise<any>;
|
|
15
16
|
declare const _default: {
|
|
@@ -27,5 +28,6 @@ declare const _default: {
|
|
|
27
28
|
apiGetList: (collectionName: string) => Promise<any>;
|
|
28
29
|
apiCreateRecordTriggerFormEvent: (collectionName: string, triggerWorkflows: string, data: any) => Promise<any>;
|
|
29
30
|
apiSubmitRecordTriggerFormEvent: (triggerWorkflows: string, data: any) => Promise<any>;
|
|
31
|
+
apiFilterList: (collectionName: string, filter: string) => Promise<any>;
|
|
30
32
|
};
|
|
31
33
|
export default _default;
|
package/dist/e2e/e2eUtils.js
CHANGED
|
@@ -21,6 +21,7 @@ __export(e2eUtils_exports, {
|
|
|
21
21
|
apiCreateWorkflow: () => apiCreateWorkflow,
|
|
22
22
|
apiCreateWorkflowNode: () => apiCreateWorkflowNode,
|
|
23
23
|
apiDeleteWorkflow: () => apiDeleteWorkflow,
|
|
24
|
+
apiFilterList: () => apiFilterList,
|
|
24
25
|
apiGetList: () => apiGetList,
|
|
25
26
|
apiGetRecord: () => apiGetRecord,
|
|
26
27
|
apiGetWorkflow: () => apiGetWorkflow,
|
|
@@ -212,6 +213,20 @@ const apiGetList = async (collectionName) => {
|
|
|
212
213
|
}
|
|
213
214
|
return await result.json();
|
|
214
215
|
};
|
|
216
|
+
const apiFilterList = async (collectionName, filter) => {
|
|
217
|
+
const api = await import_e2e.request.newContext({
|
|
218
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE
|
|
219
|
+
});
|
|
220
|
+
const state = await api.storageState();
|
|
221
|
+
const headers = getHeaders(state);
|
|
222
|
+
const result = await api.get(`/api/${collectionName}:list?${filter}`, {
|
|
223
|
+
headers
|
|
224
|
+
});
|
|
225
|
+
if (!result.ok()) {
|
|
226
|
+
throw new Error(await result.text());
|
|
227
|
+
}
|
|
228
|
+
return await result.json();
|
|
229
|
+
};
|
|
215
230
|
const apiCreateRecordTriggerFormEvent = async (collectionName, triggerWorkflows, data) => {
|
|
216
231
|
const api = await import_e2e.request.newContext({
|
|
217
232
|
storageState: process.env.PLAYWRIGHT_AUTH_FILE
|
|
@@ -297,7 +312,8 @@ var e2eUtils_default = module.exports = {
|
|
|
297
312
|
apiGetRecord,
|
|
298
313
|
apiGetList,
|
|
299
314
|
apiCreateRecordTriggerFormEvent,
|
|
300
|
-
apiSubmitRecordTriggerFormEvent
|
|
315
|
+
apiSubmitRecordTriggerFormEvent,
|
|
316
|
+
apiFilterList
|
|
301
317
|
};
|
|
302
318
|
// Annotate the CommonJS export names for ESM import in node:
|
|
303
319
|
0 && (module.exports = {
|
|
@@ -305,6 +321,7 @@ var e2eUtils_default = module.exports = {
|
|
|
305
321
|
apiCreateWorkflow,
|
|
306
322
|
apiCreateWorkflowNode,
|
|
307
323
|
apiDeleteWorkflow,
|
|
324
|
+
apiFilterList,
|
|
308
325
|
apiGetList,
|
|
309
326
|
apiGetRecord,
|
|
310
327
|
apiGetWorkflow,
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
"@nocobase/client": "0.
|
|
3
|
-
"@nocobase/utils": "0.
|
|
2
|
+
"@nocobase/client": "0.19.0-alpha.10",
|
|
3
|
+
"@nocobase/utils": "0.19.0-alpha.10",
|
|
4
4
|
"lodash": "4.17.21",
|
|
5
|
-
"@nocobase/test": "0.
|
|
6
|
-
"@nocobase/server": "0.
|
|
7
|
-
"@nocobase/database": "0.
|
|
5
|
+
"@nocobase/test": "0.19.0-alpha.10",
|
|
6
|
+
"@nocobase/server": "0.19.0-alpha.10",
|
|
7
|
+
"@nocobase/database": "0.19.0-alpha.10"
|
|
8
8
|
};
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApplicationOptions, Plugin } from '@nocobase/server';
|
|
2
2
|
import { MockServer } from '@nocobase/test';
|
|
3
|
-
interface MockServerOptions extends ApplicationOptions {
|
|
4
|
-
autoStart?: boolean;
|
|
3
|
+
export interface MockServerOptions extends ApplicationOptions {
|
|
5
4
|
collectionsPath?: string;
|
|
6
|
-
cleanDb?: boolean;
|
|
7
5
|
}
|
|
8
6
|
export declare function sleep(ms: number): Promise<unknown>;
|
|
9
|
-
export declare function getApp(
|
|
7
|
+
export declare function getApp(options?: MockServerOptions): Promise<MockServer>;
|
|
10
8
|
export default class WorkflowTestPlugin extends Plugin {
|
|
11
9
|
load(): Promise<void>;
|
|
12
10
|
}
|
|
13
|
-
export {};
|
package/dist/server/index.js
CHANGED
|
@@ -35,60 +35,43 @@ module.exports = __toCommonJS(server_exports);
|
|
|
35
35
|
var import_path = __toESM(require("path"));
|
|
36
36
|
var import_server = require("@nocobase/server");
|
|
37
37
|
var import_test = require("@nocobase/test");
|
|
38
|
-
var import_instructions = __toESM(require("./instructions"));
|
|
39
38
|
var import_functions = __toESM(require("./functions"));
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (cleanDb) {
|
|
43
|
-
await app.cleanDb();
|
|
44
|
-
}
|
|
45
|
-
await app.load();
|
|
46
|
-
if (collectionsPath) {
|
|
47
|
-
await app.db.import({ directory: collectionsPath });
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
await app.db.sync();
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error(error);
|
|
53
|
-
}
|
|
54
|
-
if (autoStart) {
|
|
55
|
-
await app.start();
|
|
56
|
-
}
|
|
57
|
-
return app;
|
|
58
|
-
}
|
|
39
|
+
var import_triggers = __toESM(require("./triggers"));
|
|
40
|
+
var import_instructions = __toESM(require("./instructions"));
|
|
59
41
|
function sleep(ms) {
|
|
60
42
|
return new Promise((resolve) => {
|
|
61
43
|
setTimeout(resolve, ms);
|
|
62
44
|
});
|
|
63
45
|
}
|
|
64
|
-
async function getApp({
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
46
|
+
async function getApp(options = {}) {
|
|
47
|
+
const { plugins = [], collectionsPath, ...others } = options;
|
|
48
|
+
class TestCollectionPlugin extends import_server.Plugin {
|
|
49
|
+
async load() {
|
|
50
|
+
if (collectionsPath) {
|
|
51
|
+
await this.db.import({ directory: collectionsPath });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return (0, import_test.createMockServer)({
|
|
56
|
+
...others,
|
|
74
57
|
plugins: [
|
|
75
58
|
[
|
|
76
59
|
"workflow",
|
|
77
60
|
{
|
|
61
|
+
triggers: import_triggers.default,
|
|
78
62
|
instructions: import_instructions.default,
|
|
79
63
|
functions: import_functions.default
|
|
80
64
|
}
|
|
81
65
|
],
|
|
82
|
-
|
|
66
|
+
"workflow-test",
|
|
67
|
+
TestCollectionPlugin,
|
|
83
68
|
...plugins
|
|
84
69
|
]
|
|
85
70
|
});
|
|
86
71
|
}
|
|
87
72
|
class WorkflowTestPlugin extends import_server.Plugin {
|
|
88
73
|
async load() {
|
|
89
|
-
await this.
|
|
90
|
-
directory: import_path.default.resolve(__dirname, "collections")
|
|
91
|
-
});
|
|
74
|
+
await this.importCollections(import_path.default.resolve(__dirname, "collections"));
|
|
92
75
|
}
|
|
93
76
|
}
|
|
94
77
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
syncTrigger: {
|
|
3
|
+
new (workflow: any): {
|
|
4
|
+
readonly workflow: any;
|
|
5
|
+
on(): void;
|
|
6
|
+
off(): void;
|
|
7
|
+
sync: boolean;
|
|
8
|
+
validateEvent(): boolean;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
asyncTrigger: {
|
|
12
|
+
new (workflow: any): {
|
|
13
|
+
readonly workflow: any;
|
|
14
|
+
on(): void;
|
|
15
|
+
off(): void;
|
|
16
|
+
validateEvent(): boolean;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var triggers_exports = {};
|
|
19
|
+
__export(triggers_exports, {
|
|
20
|
+
default: () => triggers_default
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(triggers_exports);
|
|
23
|
+
var triggers_default = {
|
|
24
|
+
syncTrigger: class {
|
|
25
|
+
constructor(workflow) {
|
|
26
|
+
this.workflow = workflow;
|
|
27
|
+
}
|
|
28
|
+
on() {
|
|
29
|
+
}
|
|
30
|
+
off() {
|
|
31
|
+
}
|
|
32
|
+
sync = true;
|
|
33
|
+
validateEvent() {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
asyncTrigger: class {
|
|
38
|
+
constructor(workflow) {
|
|
39
|
+
this.workflow = workflow;
|
|
40
|
+
}
|
|
41
|
+
on() {
|
|
42
|
+
}
|
|
43
|
+
off() {
|
|
44
|
+
}
|
|
45
|
+
validateEvent() {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
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.19.0-alpha.10",
|
|
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": "d09d81eba67339da36bcec27939a85b35d180770"
|
|
15
15
|
}
|
|
@@ -377,6 +377,7 @@ export class AggregateNode {
|
|
|
377
377
|
linkedDataTableDataRadio: Locator;
|
|
378
378
|
collectionDropDown: Locator;
|
|
379
379
|
aggregatedFieldDropDown: Locator;
|
|
380
|
+
distinctCheckBox: Locator;
|
|
380
381
|
submitButton: Locator;
|
|
381
382
|
cancelButton: Locator;
|
|
382
383
|
addNodeButton: Locator;
|
|
@@ -399,6 +400,9 @@ export class AggregateNode {
|
|
|
399
400
|
this.aggregatedFieldDropDown = page.locator(
|
|
400
401
|
'input.ant-select-selection-search-input[role="combobox"][aria-haspopup="listbox"]',
|
|
401
402
|
);
|
|
403
|
+
this.distinctCheckBox = page
|
|
404
|
+
.getByLabel('block-item-Checkbox-workflows-Distinct')
|
|
405
|
+
.locator('input.ant-checkbox-input[type="checkbox"]');
|
|
402
406
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
403
407
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
404
408
|
this.addNodeButton = page.getByLabel(`add-button-aggregate-${nodeName}`, { exact: true });
|
|
@@ -431,11 +435,11 @@ export class ManualNode {
|
|
|
431
435
|
this.assigneesDropDown = page.getByTestId('select-single');
|
|
432
436
|
this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' });
|
|
433
437
|
this.addBlockButton = page.getByLabel('schema-initializer-Grid-AddBlockButton-workflows');
|
|
434
|
-
this.triggerDataMenu = page.
|
|
435
|
-
this.nodeDataMenu = page.
|
|
438
|
+
this.triggerDataMenu = page.getByRole('menuitem', { name: 'Trigger data' });
|
|
439
|
+
this.nodeDataMenu = page.getByRole('menuitem', { name: 'Node result right' });
|
|
436
440
|
this.customFormMenu = page.getByRole('menuitem', { name: 'Custom form' });
|
|
437
|
-
this.createRecordFormMenu = page.getByRole('menuitem', { name: 'Create record form' });
|
|
438
|
-
this.updateRecordFormMenu = page.getByRole('menuitem', { name: 'Update record form' });
|
|
441
|
+
this.createRecordFormMenu = page.getByRole('menuitem', { name: 'Create record form right' });
|
|
442
|
+
this.updateRecordFormMenu = page.getByRole('menuitem', { name: 'Update record form right' });
|
|
439
443
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
440
444
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
441
445
|
this.addNodeButton = page.getByLabel(`add-button-manual-${nodeName}`, { exact: true });
|
|
@@ -450,6 +454,7 @@ export class ConditionYesNode {
|
|
|
450
454
|
basicRadio: Locator;
|
|
451
455
|
mathRadio: Locator;
|
|
452
456
|
formulaRadio: Locator;
|
|
457
|
+
conditionExpressionEditBox: Locator;
|
|
453
458
|
submitButton: Locator;
|
|
454
459
|
cancelButton: Locator;
|
|
455
460
|
addNodeButton: Locator;
|
|
@@ -460,6 +465,7 @@ export class ConditionYesNode {
|
|
|
460
465
|
this.nodeConfigure = page
|
|
461
466
|
.getByLabel(`Condition-${nodeName}`, { exact: true })
|
|
462
467
|
.getByRole('button', { name: 'Configure' });
|
|
468
|
+
this.conditionExpressionEditBox = page.getByLabel('textbox');
|
|
463
469
|
// await page.getByLabel('variable-constant').first().click();
|
|
464
470
|
// await page.getByLabel('variable-button').first().click();
|
|
465
471
|
// await page.getByLabel('select-operator-calc').first().click();
|
|
@@ -483,6 +489,7 @@ export class ConditionBranchNode {
|
|
|
483
489
|
basicRadio: Locator;
|
|
484
490
|
mathRadio: Locator;
|
|
485
491
|
formulaRadio: Locator;
|
|
492
|
+
conditionExpressionEditBox: Locator;
|
|
486
493
|
submitButton: Locator;
|
|
487
494
|
cancelButton: Locator;
|
|
488
495
|
addNoBranchNode: Locator;
|
|
@@ -495,6 +502,7 @@ export class ConditionBranchNode {
|
|
|
495
502
|
this.nodeConfigure = page
|
|
496
503
|
.getByLabel(`Condition-${nodeName}`, { exact: true })
|
|
497
504
|
.getByRole('button', { name: 'Configure' });
|
|
505
|
+
this.conditionExpressionEditBox = page.getByLabel('textbox');
|
|
498
506
|
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
499
507
|
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
500
508
|
this.addNodeButton = page.getByLabel(`add-button-condition-${nodeName}`, { exact: true });
|
|
@@ -506,6 +514,56 @@ export class ConditionBranchNode {
|
|
|
506
514
|
}
|
|
507
515
|
}
|
|
508
516
|
|
|
517
|
+
export class SQLNode {
|
|
518
|
+
readonly page: Page;
|
|
519
|
+
node: Locator;
|
|
520
|
+
nodeTitle: Locator;
|
|
521
|
+
nodeConfigure: Locator;
|
|
522
|
+
sqlEditBox: Locator;
|
|
523
|
+
submitButton: Locator;
|
|
524
|
+
cancelButton: Locator;
|
|
525
|
+
addNodeButton: Locator;
|
|
526
|
+
constructor(page: Page, nodeName: string) {
|
|
527
|
+
this.page = page;
|
|
528
|
+
this.node = page.getByLabel(`SQL action-${nodeName}`, { exact: true });
|
|
529
|
+
this.nodeTitle = page.getByLabel(`SQL action-${nodeName}`, { exact: true }).getByRole('textbox');
|
|
530
|
+
this.nodeConfigure = page
|
|
531
|
+
.getByLabel(`SQL action-${nodeName}`, { exact: true })
|
|
532
|
+
.getByRole('button', { name: 'Configure' });
|
|
533
|
+
this.sqlEditBox = page.getByLabel('block-item-WorkflowVariableRawTextArea-workflows-SQL').getByRole('textbox');
|
|
534
|
+
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
535
|
+
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
536
|
+
this.addNodeButton = page.getByLabel(`add-button-sql-${nodeName}`, { exact: true });
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export class ParallelBranchNode {
|
|
541
|
+
readonly page: Page;
|
|
542
|
+
node: Locator;
|
|
543
|
+
nodeTitle: Locator;
|
|
544
|
+
nodeConfigure: Locator;
|
|
545
|
+
addBranchButton: Locator;
|
|
546
|
+
allSucceededRadio: Locator;
|
|
547
|
+
anySucceededRadio: Locator;
|
|
548
|
+
anySucceededOrFailedRadio: Locator;
|
|
549
|
+
submitButton: Locator;
|
|
550
|
+
cancelButton: Locator;
|
|
551
|
+
addNodeButton: Locator;
|
|
552
|
+
constructor(page: Page, nodeName: string) {
|
|
553
|
+
this.page = page;
|
|
554
|
+
this.node = page.getByLabel(`Parallel branch-${nodeName}`, { exact: true });
|
|
555
|
+
this.nodeTitle = page.locator('textarea').filter({ hasText: nodeName });
|
|
556
|
+
this.nodeConfigure = page.getByLabel(`Parallel branch-${nodeName}`).getByRole('button', { name: 'Configure' });
|
|
557
|
+
this.addBranchButton = page.getByLabel(`add-button-parallel-${nodeName}-add-branch`, { exact: true });
|
|
558
|
+
this.allSucceededRadio = page.getByLabel('All succeeded', { exact: true });
|
|
559
|
+
this.anySucceededRadio = page.getByLabel('Any succeeded', { exact: true });
|
|
560
|
+
this.anySucceededOrFailedRadio = page.getByLabel('Any succeeded or failed', { exact: true });
|
|
561
|
+
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
|
562
|
+
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
|
563
|
+
this.addNodeButton = page.getByLabel(`add-button-parallel-${nodeName}`, { exact: true });
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
509
567
|
export default module.exports = {
|
|
510
568
|
CreateWorkFlow,
|
|
511
569
|
EditWorkFlow,
|
|
@@ -525,4 +583,6 @@ export default module.exports = {
|
|
|
525
583
|
ManualNode,
|
|
526
584
|
ConditionYesNode,
|
|
527
585
|
ConditionBranchNode,
|
|
586
|
+
SQLNode,
|
|
587
|
+
ParallelBranchNode,
|
|
528
588
|
};
|
package/src/e2e/e2eUtils.ts
CHANGED
|
@@ -605,6 +605,44 @@ export const apiGetList = async (collectionName: string) => {
|
|
|
605
605
|
return await result.json();
|
|
606
606
|
};
|
|
607
607
|
|
|
608
|
+
// 查询业务表list
|
|
609
|
+
export const apiFilterList = async (collectionName: string, filter: string) => {
|
|
610
|
+
const api = await request.newContext({
|
|
611
|
+
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
|
612
|
+
});
|
|
613
|
+
const state = await api.storageState();
|
|
614
|
+
const headers = getHeaders(state);
|
|
615
|
+
const result = await api.get(`/api/${collectionName}:list?${filter}`, {
|
|
616
|
+
headers,
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
if (!result.ok()) {
|
|
620
|
+
throw new Error(await result.text());
|
|
621
|
+
}
|
|
622
|
+
/*
|
|
623
|
+
{
|
|
624
|
+
"data": [
|
|
625
|
+
{
|
|
626
|
+
"id": 1,
|
|
627
|
+
"createdAt": "2023-12-12T02:43:53.793Z",
|
|
628
|
+
"updatedAt": "2023-12-12T05:41:33.300Z",
|
|
629
|
+
"key": "fzk3j2oj4el",
|
|
630
|
+
"title": "a11",
|
|
631
|
+
"enabled": true,
|
|
632
|
+
"description": null
|
|
633
|
+
}
|
|
634
|
+
],
|
|
635
|
+
"meta": {
|
|
636
|
+
"count": 1,
|
|
637
|
+
"page": 1,
|
|
638
|
+
"pageSize": 20,
|
|
639
|
+
"totalPage": 1
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
*/
|
|
643
|
+
return await result.json();
|
|
644
|
+
};
|
|
645
|
+
|
|
608
646
|
// 添加业务表单条数据触发工作流表单事件,triggerWorkflows=key1!field,key2,key3!field.subfield
|
|
609
647
|
export const apiCreateRecordTriggerFormEvent = async (collectionName: string, triggerWorkflows: string, data: any) => {
|
|
610
648
|
const api = await request.newContext({
|
|
@@ -744,4 +782,5 @@ export default module.exports = {
|
|
|
744
782
|
apiGetList,
|
|
745
783
|
apiCreateRecordTriggerFormEvent,
|
|
746
784
|
apiSubmitRecordTriggerFormEvent,
|
|
785
|
+
apiFilterList,
|
|
747
786
|
};
|
package/src/server/index.ts
CHANGED
|
@@ -1,43 +1,22 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { MockServer,
|
|
3
|
+
import { ApplicationOptions, Plugin } from '@nocobase/server';
|
|
4
|
+
import { MockServer, createMockServer } from '@nocobase/test';
|
|
5
5
|
|
|
6
|
-
import instructions from './instructions';
|
|
7
6
|
import functions from './functions';
|
|
7
|
+
import triggers from './triggers';
|
|
8
|
+
import instructions from './instructions';
|
|
8
9
|
|
|
9
|
-
interface MockServerOptions extends ApplicationOptions {
|
|
10
|
-
autoStart?: boolean;
|
|
10
|
+
export interface MockServerOptions extends ApplicationOptions {
|
|
11
11
|
collectionsPath?: string;
|
|
12
|
-
cleanDb?: boolean;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
async function createMockServer(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
await app.load();
|
|
23
|
-
|
|
24
|
-
if (collectionsPath) {
|
|
25
|
-
await app.db.import({ directory: collectionsPath });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
await app.db.sync();
|
|
30
|
-
} catch (error) {
|
|
31
|
-
console.error(error);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (autoStart) {
|
|
35
|
-
await app.start();
|
|
36
|
-
// await app.runCommand('start', '--quickstart');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return app;
|
|
40
|
-
}
|
|
14
|
+
// async function createMockServer(options: MockServerOptions) {
|
|
15
|
+
// const app = mockServer(options);
|
|
16
|
+
// await app.cleanDb();
|
|
17
|
+
// await app.runCommand('start', '--quickstart');
|
|
18
|
+
// return app;
|
|
19
|
+
// }
|
|
41
20
|
|
|
42
21
|
export function sleep(ms: number) {
|
|
43
22
|
return new Promise((resolve) => {
|
|
@@ -45,25 +24,28 @@ export function sleep(ms: number) {
|
|
|
45
24
|
});
|
|
46
25
|
}
|
|
47
26
|
|
|
48
|
-
export async function getApp({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
27
|
+
export async function getApp(options: MockServerOptions = {}): Promise<MockServer> {
|
|
28
|
+
const { plugins = [], collectionsPath, ...others } = options;
|
|
29
|
+
class TestCollectionPlugin extends Plugin {
|
|
30
|
+
async load() {
|
|
31
|
+
if (collectionsPath) {
|
|
32
|
+
await this.db.import({ directory: collectionsPath });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
54
36
|
return createMockServer({
|
|
55
|
-
...
|
|
56
|
-
autoStart,
|
|
57
|
-
cleanDb,
|
|
37
|
+
...others,
|
|
58
38
|
plugins: [
|
|
59
39
|
[
|
|
60
40
|
'workflow',
|
|
61
41
|
{
|
|
42
|
+
triggers,
|
|
62
43
|
instructions,
|
|
63
44
|
functions,
|
|
64
45
|
},
|
|
65
46
|
],
|
|
66
|
-
|
|
47
|
+
'workflow-test',
|
|
48
|
+
TestCollectionPlugin,
|
|
67
49
|
...plugins,
|
|
68
50
|
],
|
|
69
51
|
});
|
|
@@ -71,8 +53,6 @@ export async function getApp({
|
|
|
71
53
|
|
|
72
54
|
export default class WorkflowTestPlugin extends Plugin {
|
|
73
55
|
async load() {
|
|
74
|
-
await this.
|
|
75
|
-
directory: path.resolve(__dirname, 'collections'),
|
|
76
|
-
});
|
|
56
|
+
await this.importCollections(path.resolve(__dirname, 'collections'));
|
|
77
57
|
}
|
|
78
58
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
syncTrigger: class {
|
|
3
|
+
constructor(public readonly workflow) {}
|
|
4
|
+
on() {}
|
|
5
|
+
off() {}
|
|
6
|
+
sync = true;
|
|
7
|
+
validateEvent() {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
asyncTrigger: class {
|
|
12
|
+
constructor(public readonly workflow) {}
|
|
13
|
+
on() {}
|
|
14
|
+
off() {}
|
|
15
|
+
validateEvent() {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
};
|