From 1cad202745c5a691781f8aafb82c90591e2c2ef1 Mon Sep 17 00:00:00 2001 From: hongboji <116709317+hongboji@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:59:07 +0800 Subject: [PATCH] test: Workflow manual node e2e (#3451) * test: workflow manual node e2e * fix: datablocks * fix: timeout-minutes * fix: datablocks&createRecordForm * fix: createRecordForm --- .github/workflows/nocobase-test-e2e.yml | 2 +- .../src/client/__e2e__/assignees.test.ts | 0 .../client/__e2e__/createRecordForm.test.ts | 2231 +++++++++++++++++ .../client/__e2e__/customFormBlocks.test.ts | 1868 ++++++++++++++ .../src/client/__e2e__/datablocks.test.ts | 1195 +++++++++ .../client/__e2e__/updateRecordForm.test.ts | 2154 ++++++++++++++++ .../src/client/__e2e__/workflowTodo.test.ts | 233 ++ .../src/e2e/e2ePageObjectModel.ts | 8 +- .../plugin-workflow-test/src/e2e/e2eUtils.ts | 39 + 9 files changed, 7725 insertions(+), 5 deletions(-) create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/assignees.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts diff --git a/.github/workflows/nocobase-test-e2e.yml b/.github/workflows/nocobase-test-e2e.yml index f3844129d..b302bb03b 100644 --- a/.github/workflows/nocobase-test-e2e.yml +++ b/.github/workflows/nocobase-test-e2e.yml @@ -74,4 +74,4 @@ jobs: DB_USER: nocobase DB_PASSWORD: password DB_DATABASE: nocobase - timeout-minutes: 80 + timeout-minutes: 100 diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/assignees.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/assignees.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm.test.ts new file mode 100644 index 000000000..e2e5d5775 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/createRecordForm.test.ts @@ -0,0 +1,2231 @@ +import { faker } from '@faker-js/faker'; +import { + CollectionTriggerNode, + CreateWorkFlow, + EditWorkFlow, + WorkflowListRecords, + apiCreateWorkflow, + apiDeleteWorkflow, + apiGetWorkflow, + apiUpdateRecord, + apiGetWorkflowNodeExecutions, + apiUpdateWorkflowTrigger, + appendJsonCollectionName, + generalWithNoRelationalFields, + QueryRecordNode, + ManualNode, + apiGetRecord, + apiCreateWorkflowNode, + apiGetWorkflowNode, + ClculationNode, + CreateRecordNode, + AggregateNode, + apiGetList, + apiFilterList, +} from '@nocobase/plugin-workflow-test/e2e'; +import { expect, test } from '@nocobase/test/e2e'; +import { dayjs } from '@nocobase/utils'; +import { Button } from 'antd'; + +test.describe('block configuration', () => {}); + +test.describe('field configuration', () => {}); + +test.describe('field data entry', () => { + test('Collection event to add a data trigger, entering a single line of text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.orgname.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering multi-line text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'address'; + const manualNodeFieldDisplayName = '公司地址(多行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasAddress = Object.values(manualNodeJobResult).some( + (value) => (value as { address: string }).address === manualNodeRecord, + ); + expect(hasAddress).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.address.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering mobile phone number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'phone'; + const manualNodeFieldDisplayName = '负责人电话(手机号码)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasPhone = Object.values(manualNodeJobResult).some( + (value) => (value as { phone: string }).phone === manualNodeRecord, + ); + expect(hasPhone).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.phone.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering mailbox data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'email'; + const manualNodeFieldDisplayName = '电子邮箱(电子邮箱)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.internet.email(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasPhone = Object.values(manualNodeJobResult).some( + (value) => (value as { email: string }).email === manualNodeRecord, + ); + expect(hasPhone).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.email.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering integer data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'staffnum'; + const manualNodeFieldDisplayName = '员工人数(整数)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.int(); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasPhone = Object.values(manualNodeJobResult).some( + (value) => (value as { staffnum: number }).staffnum === manualNodeRecord, + ); + expect(hasPhone).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.staffnum.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'regcapital'; + const manualNodeFieldDisplayName = '注册资本(数字)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.float({ min: 0, max: 999999999, precision: 2 }); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasRegcapital = Object.values(manualNodeJobResult).some( + (value) => (value as { regcapital: number }).regcapital === manualNodeRecord, + ); + expect(hasRegcapital).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.regcapital.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering percentage data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'insuranceratio'; + const manualNodeFieldDisplayName = '参保占比(百分比)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // 定义获取2位小数 + const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasInsuranceratio = Object.values(manualNodeJobResult).some( + (value) => (value as { insuranceratio: number }).insuranceratio === manualNodeRecord / 100, + ); + expect(hasInsuranceratio).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.insuranceratio.toString()).toBe((manualNodeRecord / 100).toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering checkbox data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'isenable'; + const manualNodeFieldDisplayName = '是否启用(勾选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float(); + await page.getByRole('checkbox').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { isenable: boolean }).isenable === true, + ); + expect(hasIsenable).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.isenable).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering single select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_singleselect'; + const manualNodeFieldDisplayName = '公司状态(下拉单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByTestId('select-single').click(); + await page.getByRole('option', { name: '存续' }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_singleselect: string }).status_singleselect === '1', + ); + expect(hasIsenable).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.status_singleselect).toBe('1'); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering multiple select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_multipleselect'; + const manualNodeFieldDisplayName = '经营范围(下拉多选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByTestId('select-multiple').click(); + await page.getByRole('option', { name: '软件销售', exact: true }).click(); + await page.getByRole('option', { name: '软件开发', exact: true }).click(); + await page.getByTestId('select-multiple').click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_multipleselect')) { + resultFieldValue = manualNodeJobResult[key]['range_multipleselect']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(JSON.stringify(getRecordsObj.range_multipleselect)).toBe(JSON.stringify(expectFieldValue)); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering radio group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_radio'; + const manualNodeFieldDisplayName = '公司状态(单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByLabel('存续').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_radio: string }).status_radio === '1', + ); + expect(hasIsenable).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.status_radio).toBe('1'); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering checkbox group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_check'; + const manualNodeFieldDisplayName = '经营范围(复选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByLabel('软件销售', { exact: true }).check(); + await page.getByLabel('软件开发', { exact: true }).check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_check')) { + resultFieldValue = manualNodeJobResult[key]['range_check']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(JSON.stringify(getRecordsObj.range_check)).toBe(JSON.stringify(expectFieldValue)); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering datetime data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'establishdate'; + const manualNodeFieldDisplayName = '成立日期(日期)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = dayjs().format('YYYY-MM-DD'); + await page.getByPlaceholder('Select date').click(); + await page.getByTitle(manualNodeRecord.toString()).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'establishdate')) { + resultFieldValue = manualNodeJobResult[key]['establishdate']; + break; + } + } + const now = new Date(); + now.setHours(0, 0, 0, 0); + const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const timeWithTimeZone = now.toLocaleString('en-US', { timeZone: timeZone }); + // 转换为0时区的时间 + const timeInUTC = new Date(timeWithTimeZone).toISOString(); + + expect(resultFieldValue).toBe(timeInUTC); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); +}); + +test.describe('relation field data entry', () => {}); + +test.describe('action button', () => { + test('Collection event to add a data trigger, entering a single line of text data, continue the process', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.orgname.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering a single line of text data, terminate the process', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + // await page.mouse.click(300, 0); + await page.getByLabel(`schema-initializer-ActionBar-AddActionButton-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Terminate the process' }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Terminate the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(-5); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj.orgname.toString()).toBe(manualNodeRecord.toString()); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering a single line of text data, save temporarily', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + // await page.mouse.click(300, 0); + await page.getByLabel(`schema-initializer-ActionBar-AddActionButton-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Save temporarily' }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Save temporarily' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(0); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + const getRecords = await apiGetRecord(manualNodeCollectionName, 1); + const getRecordsObj = JSON.parse(JSON.stringify(getRecords)); + expect(getRecordsObj).toBe(null); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts new file mode 100644 index 000000000..a969e7ee3 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/customFormBlocks.test.ts @@ -0,0 +1,1868 @@ +import { faker } from '@faker-js/faker'; +import { + CollectionTriggerNode, + CreateWorkFlow, + EditWorkFlow, + WorkflowListRecords, + apiCreateWorkflow, + apiDeleteWorkflow, + apiGetWorkflow, + apiUpdateRecord, + apiGetWorkflowNodeExecutions, + apiUpdateWorkflowTrigger, + appendJsonCollectionName, + generalWithNoRelationalFields, + QueryRecordNode, + ManualNode, + apiGetRecord, + apiCreateWorkflowNode, + apiGetWorkflowNode, + ClculationNode, + CreateRecordNode, + AggregateNode, + apiGetList, + apiFilterList, +} from '@nocobase/plugin-workflow-test/e2e'; +import { expect, test } from '@nocobase/test/e2e'; +import { dayjs } from '@nocobase/utils'; + +test.describe('block configuration', () => {}); + +test.describe('field configuration', () => {}); + +test.describe('field data entry', () => { + test('Collection event to add a data trigger, entering a single line of text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Single line text' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering multi-line text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'address'; + const manualNodeFieldDisplayName = '公司地址(多行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Long text' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasAddress = Object.values(manualNodeJobResult).some( + (value) => (value as { address: string }).address === manualNodeRecord, + ); + expect(hasAddress).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering mobile phone number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'phone'; + const manualNodeFieldDisplayName = '负责人电话(手机号码)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Phone' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasPhone = Object.values(manualNodeJobResult).some( + (value) => (value as { phone: string }).phone === manualNodeRecord, + ); + expect(hasPhone).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering mailbox data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'email'; + const manualNodeFieldDisplayName = '电子邮箱(电子邮箱)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Email' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.internet.email(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasEmail = Object.values(manualNodeJobResult).some( + (value) => (value as { email: string }).email === manualNodeRecord, + ); + expect(hasEmail).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering integer data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'staffnum'; + const manualNodeFieldDisplayName = '员工人数(整数)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Integer' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.int(); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasStaffnum = Object.values(manualNodeJobResult).some( + (value) => (value as { staffnum: number }).staffnum === manualNodeRecord, + ); + expect(hasStaffnum).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'regcapital'; + const manualNodeFieldDisplayName = '注册资本(数字)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Number' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.float(); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasRegcapital = Object.values(manualNodeJobResult).some( + (value) => (value as { regcapital: number }).regcapital === manualNodeRecord, + ); + expect(hasRegcapital).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering percentage data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'insuranceratio'; + const manualNodeFieldDisplayName = '参保占比(百分比)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Percent' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasRegcapital = Object.values(manualNodeJobResult).some( + (value) => (value as { insuranceratio: number }).insuranceratio === manualNodeRecord / 100, + ); + expect(hasRegcapital).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering checkbox data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'isenable'; + const manualNodeFieldDisplayName = '是否启用(勾选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Checkbox', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByRole('checkbox').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { isenable: boolean }).isenable === true, + ); + expect(hasIsenable).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering single select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_singleselect'; + const manualNodeFieldDisplayName = '公司状态(下拉单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Single select', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').first().fill('1'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(1).fill('存续'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(2).fill('2'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(3).fill('在业'); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByTestId('select-single').click(); + await page.getByRole('option', { name: '存续' }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_singleselect: string }).status_singleselect === '1', + ); + expect(hasIsenable).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering multiple select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_multipleselect'; + const manualNodeFieldDisplayName = '经营范围(下拉多选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Multiple select', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').first().fill('F3134'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(1).fill('软件销售'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(2).fill('I3006'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(3).fill('软件开发'); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByTestId('select-multiple').click(); + await page.getByRole('option', { name: '软件销售', exact: true }).click(); + await page.getByRole('option', { name: '软件开发', exact: true }).click(); + await page.getByTestId('select-multiple').click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_multipleselect')) { + resultFieldValue = manualNodeJobResult[key]['range_multipleselect']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering radio group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_radio'; + const manualNodeFieldDisplayName = '公司状态(单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Radio group', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').first().fill('1'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(1).fill('存续'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(2).fill('2'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(3).fill('在业'); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByLabel('存续').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_radio: string }).status_radio === '1', + ); + expect(hasIsenable).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering checkbox group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_check'; + const manualNodeFieldDisplayName = '经营范围(复选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Checkbox group', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByRole('button', { name: 'Add option' }).click(); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').first().fill('F3134'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(1).fill('软件销售'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(2).fill('I3006'); + await page.getByLabel('block-item-ArrayTable-').getByRole('textbox').nth(3).fill('软件开发'); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByLabel('软件销售', { exact: true }).check(); + await page.getByLabel('软件开发', { exact: true }).check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_check')) { + resultFieldValue = manualNodeJobResult[key]['range_check']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, entering datetime data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'establishdate'; + const manualNodeFieldDisplayName = '成立日期(日期)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Datetime', exact: true }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill(manualNodeFieldDisplayName); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill(manualNodeFieldName); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = dayjs().format('YYYY-MM-DD'); + await page.getByPlaceholder('Select date').click(); + await page.getByTitle(manualNodeRecord.toString()).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'establishdate')) { + resultFieldValue = manualNodeJobResult[key]['establishdate']; + break; + } + } + const now = new Date(); + now.setHours(0, 0, 0, 0); + const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const timeWithTimeZone = now.toLocaleString('en-US', { timeZone: timeZone }); + // 转换为0时区的时间 + const timeInUTC = new Date(timeWithTimeZone).toISOString(); + + expect(resultFieldValue).toBe(timeInUTC); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts new file mode 100644 index 000000000..96c1b4608 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/datablocks.test.ts @@ -0,0 +1,1195 @@ +import { faker } from '@faker-js/faker'; +import { + CollectionTriggerNode, + CreateWorkFlow, + EditWorkFlow, + WorkflowListRecords, + apiCreateWorkflow, + apiDeleteWorkflow, + apiGetWorkflow, + apiUpdateRecord, + apiGetWorkflowNodeExecutions, + apiUpdateWorkflowTrigger, + appendJsonCollectionName, + generalWithNoRelationalFields, + QueryRecordNode, + ManualNode, + apiGetRecord, + apiCreateWorkflowNode, + apiGetWorkflowNode, + ClculationNode, + CreateRecordNode, + AggregateNode, + apiGetList, + apiFilterList, +} from '@nocobase/plugin-workflow-test/e2e'; +import { expect, test } from '@nocobase/test/e2e'; +import { dayjs } from '@nocobase/utils'; + +test.describe('field data', () => { + test('Collection event to add a data trigger, get a single line of text data for the trigger node', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.triggerDataMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: triggerNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(triggerNodeCollectionRecordOne)).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get calculation node data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置前置计算节点 + const preCalculationNodeTitle = 'calculation' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preCalculationNodeData = { + type: 'calculation', + upstreamId: null, + branchIndex: null, + title: preCalculationNodeTitle, + config: { engine: 'math.js', expression: '{{$context.data.orgname}}' }, + }; + const preCalculationNode = await apiCreateWorkflowNode(workflowId, preCalculationNodeData); + const preCalculationNodeObj = JSON.parse(JSON.stringify(preCalculationNode)); + const preCalculationNodeId = preCalculationNodeObj.id; + const getPreCalculationNode = await apiGetWorkflowNode(preCalculationNodeId); + const preCalculationNodeKey = getPreCalculationNode.key; + + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preCalculationNodePom = new ClculationNode(page, preCalculationNodeTitle); + await preCalculationNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preCalculationNodeTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(triggerNodeCollectionRecordOne)).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get query record node data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置前置查询节点 + const preQueryRecordNodeTitle = 'Query record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preQueryRecordNodeData = { + type: 'query', + upstreamId: null, + branchIndex: null, + title: preQueryRecordNodeTitle, + config: { + collection: triggerNodeCollectionName, + params: { + filter: { $and: [{ id: { $eq: '{{$context.data.id}}' } }] }, + sort: [], + page: 1, + pageSize: 20, + appends: [], + }, + }, + }; + const preQueryRecordNode = await apiCreateWorkflowNode(workflowId, preQueryRecordNodeData); + const preQueryRecordNodeObj = JSON.parse(JSON.stringify(preQueryRecordNode)); + const preQueryRecordNodeId = preQueryRecordNodeObj.id; + const getPreQueryRecordNode = await apiGetWorkflowNode(preQueryRecordNodeId); + const preQueryRecordNodeKey = getPreQueryRecordNode.key; + + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preQueryRecordNodePom = new QueryRecordNode(page, preQueryRecordNodeTitle); + await preQueryRecordNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preQueryRecordNodeTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: triggerNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(triggerNodeCollectionRecordOne)).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get create record node data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + const createRecordNodeAppendText = 'c' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建create record节点数据表 + const createRecordNodeCollectionDisplayName = `自动>组织[普通表]${createRecordNodeAppendText}`; + const createRecordNodeCollectionName = `tt_amt_org${createRecordNodeAppendText}`; + const createRecordNodeFieldName = 'orgname'; + const createRecordNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), createRecordNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + + //配置前置添加数据节点 + const preCreateRecordNodeTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preCreateRecordNodeData = { + type: 'create', + upstreamId: null, + branchIndex: null, + title: preCreateRecordNodeTitle, + config: { + params: { values: { orgname: '{{$context.data.orgname}}' }, appends: [] }, + collection: createRecordNodeCollectionName, + }, + }; + const preCreateRecordNode = await apiCreateWorkflowNode(workflowId, preCreateRecordNodeData); + const preCreateRecordNodeObj = JSON.parse(JSON.stringify(preCreateRecordNode)); + const preCreateRecordNodeId = preCreateRecordNodeObj.id; + const getPreCreateRecordNode = await apiGetWorkflowNode(preCreateRecordNodeId); + const preCreateRecordNodeKey = getPreCreateRecordNode.key; + + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preCreateRecordNodePom = new CreateRecordNode(page, preCreateRecordNodeTitle); + await preCreateRecordNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preCreateRecordNodeTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: triggerNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(triggerNodeCollectionRecordOne)).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get aggregate node data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + const aggregateNodeAppendText = 'c' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建aggregate节点数据表 + const aggregateNodeCollectionDisplayName = `自动>组织[普通表]${aggregateNodeAppendText}`; + const aggregateNodeCollectionName = `tt_amt_org${aggregateNodeAppendText}`; + const aggregateNodeFieldName = 'orgname'; + const aggregateNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), aggregateNodeAppendText) + .collections, + ); + const aggregateNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10 }, + ]; + const aggregateNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '1', staffnum: 20 }, + ]; + const aggregateNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '1', staffnum: 30 }, + ]; + const aggregateNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '1', staffnum: 40 }, + ]; + const aggregateNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '2', staffnum: 10 }, + ]; + const aggregateNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '2', staffnum: 20 }, + ]; + const aggregateNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '2', staffnum: 30 }, + ]; + const aggregateNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '2', staffnum: 40 }, + ]; + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordOne); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordTwo); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordThree); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordFour); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordFive); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordSix); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordSeven); + await mockRecords(aggregateNodeCollectionName, aggregateNodeCollectioRecordEight); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + + //配置前置聚合查询节点 + const preAggregateNodeTitle = 'Aggregate' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preAggregateNodeData = { + type: 'aggregate', + upstreamId: null, + branchIndex: null, + title: preAggregateNodeTitle, + config: { + aggregator: 'count', + associated: false, + params: { field: 'id', filter: { $and: [] } }, + collection: aggregateNodeCollectionName, + }, + }; + const preAggregateNode = await apiCreateWorkflowNode(workflowId, preAggregateNodeData); + const preAggregateNodeObj = JSON.parse(JSON.stringify(preAggregateNode)); + const preAggregateNodeId = preAggregateNodeObj.id; + const getPreAggregateNode = await apiGetWorkflowNode(preAggregateNodeId); + const preAggregateNodeKey = getPreAggregateNode.key; + + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preAggregateNodePom = new AggregateNode(page, preAggregateNodeTitle); + await preAggregateNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preAggregateNodeTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // await expect(page.getByText('8')).toBeAttached(); + await expect( + page + .getByLabel(`block-item-CardItem-users_jobs-workflow-todo-${preAggregateNodeTitle}`) + .locator('.ant-card-body') + .getByText('8'), + ).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get single line text data for manual node custom form', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + const preManualNodeAppendText = 'c' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建前置Manual节点数据表 + const preManualNodeCollectionDisplayName = `自动>组织[普通表]${preManualNodeAppendText}`; + const preManualNodeCollectionName = `tt_amt_org${preManualNodeAppendText}`; + const preManualNodeFieldName = 'orgname'; + const preManualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), preManualNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置前置Manual节点 + const preManualNodeTitle = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preManualNodeData = { + type: 'manual', + upstreamId: null, + branchIndex: null, + title: preManualNodeTitle, + config: { assignees: [1], schema: null, forms: {} }, + }; + const preManualNode = await apiCreateWorkflowNode(workflowId, preManualNodeData); + const preManualNodeObj = JSON.parse(JSON.stringify(preManualNode)); + const preAggregateNodeId = preManualNodeObj.id; + const getAggregateNode = await apiGetWorkflowNode(preAggregateNodeId); + const preAggregateNodeKey = getAggregateNode.key; + + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preManualNodePom = new ManualNode(page, preManualNodeTitle); + await preManualNodePom.nodeConfigure.click(); + await preManualNodePom.configureUserInterfaceButton.click(); + await preManualNodePom.addBlockButton.hover(); + await preManualNodePom.customFormMenu.click(); + await page.mouse.move(300, 0, { steps: 100 }); + // 获取自定义表单的随机值 + const configureFieldsButton = page.locator('button[aria-label^="schema-initializer-Grid-AddCustomFormField-"]'); + const ariaLabel = await configureFieldsButton.getAttribute('aria-label'); + const randomValue = ariaLabel.split('-').pop(); + + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByLabel(`designer-schema-settings-CardItem-SimpleDesigner-${randomValue}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Form' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.locator(`button[aria-label^="schema-initializer-Grid-AddCustomFormField-${randomValue}"]`).hover(); + await page.getByRole('menuitem', { name: 'Single line text' }).click(); + await page + .getByLabel(`block-item-Input-${randomValue}-Field display name`) + .getByRole('textbox') + .fill('公司名称(单行文本)'); + await page.getByLabel(`block-item-Input-${randomValue}-Field name`).getByRole('textbox').fill('orgname'); + await page.getByLabel(`action-Action-Submit-${randomValue}`).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await preManualNodePom.submitButton.click(); + await page.waitForLoadState('networkidle'); + //配置Manual节点 + await preManualNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preManualNodeTitle }).hover(); + await page.getByRole('menuitem', { name: blockTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: '公司名称(单行文本)' }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${preManualNodeTitle}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const preManualNodeRecord = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(preManualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'Task right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'Title' }).click(); + await page.getByRole('textbox').fill(manualNodeName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(preManualNodeRecord)).toBeAttached(); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get single line text data for manual node create record form', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + const preManualNodeAppendText = 'c' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建前置Manual节点数据表 + const preManualNodeCollectionDisplayName = `自动>组织[普通表]${preManualNodeAppendText}`; + const preManualNodeCollectionName = `tt_amt_org${preManualNodeAppendText}`; + const preManualNodeFieldName = 'orgname'; + const preManualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), preManualNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置前置Manual节点 + const preManualNodeTitle = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preManualNodeData = { + type: 'manual', + upstreamId: null, + branchIndex: null, + title: preManualNodeTitle, + config: { assignees: [1], schema: null, forms: {} }, + }; + const preManualNode = await apiCreateWorkflowNode(workflowId, preManualNodeData); + const preManualNodeObj = JSON.parse(JSON.stringify(preManualNode)); + const preAggregateNodeId = preManualNodeObj.id; + const getAggregateNode = await apiGetWorkflowNode(preAggregateNodeId); + const preAggregateNodeKey = getAggregateNode.key; + + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preManualNodePom = new ManualNode(page, preManualNodeTitle); + await preManualNodePom.nodeConfigure.click(); + await preManualNodePom.configureUserInterfaceButton.click(); + await preManualNodePom.addBlockButton.hover(); + await preManualNodePom.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: preManualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${preManualNodeCollectionName}"]`) + .hover(); + await page + .getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${preManualNodeCollectionName}`) + .hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${preManualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: triggerNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await preManualNodePom.submitButton.click(); + await page.waitForLoadState('networkidle'); + //配置Manual节点 + await preManualNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preManualNodeTitle }).hover(); + await page.getByRole('menuitem', { name: blockTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: '公司名称(单行文本)' }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${preManualNodeTitle}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const preManualNodeRecord = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(preManualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'Task right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'Title' }).click(); + await page.getByRole('textbox').fill(manualNodeName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(preManualNodeRecord)).toBeAttached(); + + const createNodeCollectionData = await apiGetList(preManualNodeCollectionName); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(1); + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, get single line text data for manual node update record form', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + const preManualNodeAppendText = 'c' + dayjs().format('HHmmss').toString(); + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建前置Manual节点数据表 + const preManualNodeCollectionDisplayName = `自动>组织[普通表]${preManualNodeAppendText}`; + const preManualNodeCollectionName = `tt_amt_org${preManualNodeAppendText}`; + const preManualNodeFieldName = 'orgname'; + const preManualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), preManualNodeAppendText) + .collections, + ); + const preManualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10 }, + ]; + const preManualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '1', staffnum: 20 }, + ]; + const preManualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '1', staffnum: 30 }, + ]; + const preManualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '1', staffnum: 40 }, + ]; + const preManualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '2', staffnum: 10 }, + ]; + const preManualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '2', staffnum: 20 }, + ]; + const preManualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '2', staffnum: 30 }, + ]; + const preManualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '2', staffnum: 40 }, + ]; + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordOne); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordTwo); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordThree); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordFour); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordFive); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordSix); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordSeven); + await mockRecords(preManualNodeCollectionName, preManualNodeCollectioRecordEight); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置前置Manual节点 + const preManualNodeTitle = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const preManualNodeData = { + type: 'manual', + upstreamId: null, + branchIndex: null, + title: preManualNodeTitle, + config: { assignees: [1], schema: null, forms: {} }, + }; + const preManualNode = await apiCreateWorkflowNode(workflowId, preManualNodeData); + const preManualNodeObj = JSON.parse(JSON.stringify(preManualNode)); + const preAggregateNodeId = preManualNodeObj.id; + const getAggregateNode = await apiGetWorkflowNode(preAggregateNodeId); + const preAggregateNodeKey = getAggregateNode.key; + + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const preManualNodePom = new ManualNode(page, preManualNodeTitle); + await preManualNodePom.nodeConfigure.click(); + await preManualNodePom.configureUserInterfaceButton.click(); + await preManualNodePom.addBlockButton.hover(); + await preManualNodePom.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: preManualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${preManualNodeCollectionName}"]`) + .hover(); + await page + .getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${preManualNodeCollectionName}`) + .hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Update record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${preManualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: triggerNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await preManualNodePom.submitButton.click(); + await page.waitForLoadState('networkidle'); + //配置Manual节点 + await preManualNodePom.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.nodeDataMenu.hover(); + await page.getByRole('menuitem', { name: preManualNodeTitle }).hover(); + await page.getByRole('menuitem', { name: blockTitle }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.getByText('Configure fields').hover(); + await page.getByRole('menuitem', { name: '公司名称(单行文本)' }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${preManualNodeTitle}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const preManualNodeRecord = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(preManualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'Task right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'Title' }).click(); + await page.getByRole('textbox').fill(manualNodeName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await expect(page.getByText(preManualNodeRecord)).toBeAttached(); + const filter = `pageSize=20&page=1&filter={"$and":[{"orgname":{"$eq":"${preManualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(preManualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); +}); + +test.describe('relation field data', () => {}); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts new file mode 100644 index 000000000..83fb84d85 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/updateRecordForm.test.ts @@ -0,0 +1,2154 @@ +import { faker } from '@faker-js/faker'; +import { + CollectionTriggerNode, + CreateWorkFlow, + EditWorkFlow, + WorkflowListRecords, + apiCreateWorkflow, + apiDeleteWorkflow, + apiGetWorkflow, + apiUpdateRecord, + apiGetWorkflowNodeExecutions, + apiUpdateWorkflowTrigger, + appendJsonCollectionName, + generalWithNoRelationalFields, + QueryRecordNode, + ManualNode, + apiGetRecord, + apiCreateWorkflowNode, + apiGetWorkflowNode, + ClculationNode, + CreateRecordNode, + AggregateNode, + apiGetList, + apiFilterList, +} from '@nocobase/plugin-workflow-test/e2e'; +import { expect, test } from '@nocobase/test/e2e'; +import { dayjs } from '@nocobase/utils'; + +test.describe('block configuration', () => {}); + +test.describe('field configuration', () => {}); + +test.describe('field data update', () => { + test('Collection event to add a data trigger, update single-line text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasOrgname = Object.values(manualNodeJobResult).some( + (value) => (value as { orgname: string }).orgname === manualNodeRecord, + ); + expect(hasOrgname).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"orgname":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update multi-line text data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'address'; + const manualNodeFieldDisplayName = '公司地址(多行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ address: '公司地址(多行文本)1', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ address: '公司地址(多行文本)2', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ address: '公司地址(多行文本)3', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ address: '公司地址(多行文本)4', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ address: '公司地址(多行文本)5', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ address: '公司地址(多行文本)6', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ address: '公司地址(多行文本)7', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ address: '公司地址(多行文本)8', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasAddress = Object.values(manualNodeJobResult).some( + (value) => (value as { address: string }).address === manualNodeRecord, + ); + expect(hasAddress).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"address":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update mobile phone number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'phone'; + const manualNodeFieldDisplayName = '负责人电话(手机号码)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ phone: '负责人电话(手机号码)1', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ phone: '负责人电话(手机号码)2', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ phone: '负责人电话(手机号码)3', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ phone: '负责人电话(手机号码)4', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ phone: '负责人电话(手机号码)5', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ phone: '负责人电话(手机号码)6', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ phone: '负责人电话(手机号码)7', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ phone: '负责人电话(手机号码)8', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = manualNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasPhone = Object.values(manualNodeJobResult).some( + (value) => (value as { phone: string }).phone === manualNodeRecord, + ); + expect(hasPhone).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"phone":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update Email Data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'email'; + const manualNodeFieldDisplayName = '电子邮箱(电子邮箱)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ email: '1@1.com', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ email: '2@2.com', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ email: '3@3.com', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ email: '4@4.com', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ email: '5@5.com', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ email: '6@6.com', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ email: '7@7.com', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ email: '8@8.com', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.internet.email(); + await page.getByRole('textbox').fill(manualNodeRecord); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasEmail = Object.values(manualNodeJobResult).some( + (value) => (value as { email: string }).email === manualNodeRecord, + ); + expect(hasEmail).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"email":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update integer data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'staffnum'; + const manualNodeFieldDisplayName = '员工人数(整数)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.int(); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasStaffnum = Object.values(manualNodeJobResult).some( + (value) => (value as { staffnum: number }).staffnum === manualNodeRecord, + ); + expect(hasStaffnum).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"staffnum":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update number data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'regcapital'; + const manualNodeFieldDisplayName = '注册资本(数字)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [{ orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10 }]; + const manualNodeCollectioRecordTwo = [{ orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20 }]; + const manualNodeCollectioRecordThree = [{ orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30 }]; + const manualNodeCollectioRecordFour = [{ orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40 }]; + const manualNodeCollectioRecordFive = [{ orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10 }]; + const manualNodeCollectioRecordSix = [{ orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20 }]; + const manualNodeCollectioRecordSeven = [{ orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30 }]; + const manualNodeCollectioRecordEight = [{ orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40 }]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.float(); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasRegcapital = Object.values(manualNodeJobResult).some( + (value) => (value as { regcapital: number }).regcapital === manualNodeRecord, + ); + expect(hasRegcapital).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"regcapital":{"$eq":"${manualNodeRecord}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update percentage data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'insuranceratio'; + const manualNodeFieldDisplayName = '参保占比(百分比)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10, insuranceratio: 1.11 }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22 }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33 }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44 }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11 }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22 }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33 }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44 }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByRole('spinbutton').fill(manualNodeRecord.toString()); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasRegcapital = Object.values(manualNodeJobResult).some( + (value) => (value as { insuranceratio: number }).insuranceratio === manualNodeRecord / 100, + ); + expect(hasRegcapital).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"insuranceratio":{"$eq":"${manualNodeRecord / 100}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update checkbox data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'isenable'; + const manualNodeFieldDisplayName = '是否启用(勾选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '1', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByRole('checkbox').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { isenable: boolean }).isenable === true, + ); + expect(hasIsenable).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"isenable":{"$eq":true}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update single select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_singleselect'; + const manualNodeFieldDisplayName = '公司状态(下拉单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '2', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByTestId('select-single').click(); + await page.getByRole('option', { name: '存续' }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_singleselect: string }).status_singleselect === '1', + ); + expect(hasIsenable).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"status_singleselect":{"$eq":"1"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update multiple select data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_multipleselect'; + const manualNodeFieldDisplayName = '经营范围(下拉多选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '2', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByTestId('select-multiple').click(); + await page.getByRole('option', { name: '软件销售', exact: true }).click(); + await page.getByRole('option', { name: '软件开发', exact: true }).click(); + await page.getByTestId('select-multiple').click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_multipleselect')) { + resultFieldValue = manualNodeJobResult[key]['range_multipleselect']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"range_multipleselect":{"$match":["F3134","I3006"]}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update radio group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'status_radio'; + const manualNodeFieldDisplayName = '公司状态(单选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '2', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + // const manualNodeRecord = faker.number.float({ min: 0, max: 100, precision: 2 }); + await page.getByLabel('存续').check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + const hasIsenable = Object.values(manualNodeJobResult).some( + (value) => (value as { status_radio: string }).status_radio === '1', + ); + expect(hasIsenable).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"status_radio":{"$eq":"1"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update checkbox group data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'range_check'; + const manualNodeFieldDisplayName = '经营范围(复选)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '2', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + await page.getByLabel('软件销售', { exact: true }).check(); + await page.getByLabel('软件开发', { exact: true }).check(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + const expectFieldValue = ['F3134', 'I3006']; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'range_check')) { + resultFieldValue = manualNodeJobResult[key]['range_check']; + break; + } + } + const isEqual = JSON.stringify(resultFieldValue) === JSON.stringify(expectFieldValue); + expect(isEqual).toBe(true); + + const filter = `pageSize=20&page=1&filter={"$and":[{"range_check":{"$match":["F3134","I3006"]}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); + + test('Collection event to add a data trigger, update datetime data', async ({ + page, + mockPage, + mockCollections, + mockRecords, + }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'establishdate'; + const manualNodeFieldDisplayName = '成立日期(日期)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + const manualNodeCollectioRecordOne = [ + { orgname: '公司名称(单行文本)1', status_singleselect: '2', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordTwo = [ + { orgname: '公司名称(单行文本)2', status_singleselect: '2', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordThree = [ + { orgname: '公司名称(单行文本)3', status_singleselect: '3', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordFour = [ + { orgname: '公司名称(单行文本)4', status_singleselect: '4', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + const manualNodeCollectioRecordFive = [ + { orgname: '公司名称(单行文本)5', status_singleselect: '5', staffnum: 10, insuranceratio: 1.11, isenable: false }, + ]; + const manualNodeCollectioRecordSix = [ + { orgname: '公司名称(单行文本)6', status_singleselect: '6', staffnum: 20, insuranceratio: 2.22, isenable: false }, + ]; + const manualNodeCollectioRecordSeven = [ + { orgname: '公司名称(单行文本)7', status_singleselect: '7', staffnum: 30, insuranceratio: 3.33, isenable: false }, + ]; + const manualNodeCollectioRecordEight = [ + { orgname: '公司名称(单行文本)8', status_singleselect: '8', staffnum: 40, insuranceratio: 4.44, isenable: false }, + ]; + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordOne); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordTwo); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordThree); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFour); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordFive); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSix); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordSeven); + await mockRecords(manualNodeCollectionName, manualNodeCollectioRecordEight); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.updateRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-UpdateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = + triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page + .locator(`//td[span[text()="${manualNodeName}"]]`) + .locator('xpath=preceding-sibling::td[1]') + .locator('text=View') + .click(); + const manualNodeRecord = dayjs().format('YYYY-MM-DD'); + await page.getByPlaceholder('Select date').click(); + await page.getByTitle(manualNodeRecord.toString()).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + await page.getByRole('button', { name: 'Continue the process' }).click(); + + await page.waitForTimeout(1000); + const getWorkflowNodeExecutions = await apiGetWorkflowNodeExecutions(workflowId); + const getWorkflowNodeExecutionsObj = JSON.parse(JSON.stringify(getWorkflowNodeExecutions)); + getWorkflowNodeExecutionsObj.sort(function (a: { id: number }, b: { id: number }) { + return b.id - a.id; + }); + const jobs = getWorkflowNodeExecutionsObj[0].jobs; + const manualNodeJob = jobs.find((job) => job.nodeId.toString() === manualNodeId); + const manualNodeJobStatus = manualNodeJob.status; + expect(manualNodeJobStatus).toBe(1); + + const manualNodeJobResult = manualNodeJob.result; + let resultFieldValue = ''; + for (const key in manualNodeJobResult) { + if (Object.prototype.hasOwnProperty.call(manualNodeJobResult[key], 'establishdate')) { + resultFieldValue = manualNodeJobResult[key]['establishdate']; + break; + } + } + const now = new Date(); + now.setHours(0, 0, 0, 0); + const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const timeWithTimeZone = now.toLocaleString('en-US', { timeZone: timeZone }); + // 转换为0时区的时间 + const timeInUTC = new Date(timeWithTimeZone).toISOString(); + + const filter = `pageSize=20&page=1&filter={"$and":[{"establishdate":{"$eq":"${timeInUTC}"}}]}`; + const createNodeCollectionData = await apiFilterList(manualNodeCollectionName, filter); + const createNodeCollectionDataObj = JSON.parse(JSON.stringify(createNodeCollectionData)); + expect(createNodeCollectionDataObj.meta.count).toBe(8); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); + }); +}); + +test.describe('relation field data update', () => {}); + +test.describe('action button', () => {}); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts new file mode 100644 index 000000000..6fa027703 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/__e2e__/workflowTodo.test.ts @@ -0,0 +1,233 @@ +import { faker } from '@faker-js/faker'; +import { + CollectionTriggerNode, + apiCreateWorkflow, + apiDeleteWorkflow, + apiGetWorkflow, + apiUpdateWorkflowTrigger, + appendJsonCollectionName, + generalWithNoRelationalFields, + ManualNode, +} from '@nocobase/plugin-workflow-test/e2e'; +import { expect, test } from '@nocobase/test/e2e'; +import { dayjs } from '@nocobase/utils'; + +test('filter task node', async ({ page, mockPage, mockCollections, mockRecords }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'Task right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'Title' }).click(); + await page.getByRole('textbox').fill(manualNodeName); + await page.getByRole('button', { name: 'Submit' }).click(); + + // 3、预期结果:列表中出现筛选的工作流 + await expect(page.getByText(manualNodeName)).toBeAttached(); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); +}); + +test('filter workflow name', async ({ page, mockPage, mockCollections, mockRecords }) => { + //数据表后缀标识 + const triggerNodeAppendText = 'a' + faker.string.alphanumeric(4); + const manualNodeAppendText = 'b' + dayjs().format('HHmmss').toString(); + + // 创建触发器节点数据表 + const triggerNodeCollectionDisplayName = `自动>组织[普通表]${triggerNodeAppendText}`; + const triggerNodeCollectionName = `tt_amt_org${triggerNodeAppendText}`; + const triggerNodeFieldName = 'orgname'; + const triggerNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), triggerNodeAppendText) + .collections, + ); + // 创建Manual节点数据表 + const manualNodeCollectionDisplayName = `自动>组织[普通表]${manualNodeAppendText}`; + const manualNodeCollectionName = `tt_amt_org${manualNodeAppendText}`; + const manualNodeFieldName = 'orgname'; + const manualNodeFieldDisplayName = '公司名称(单行文本)'; + await mockCollections( + appendJsonCollectionName(JSON.parse(JSON.stringify(generalWithNoRelationalFields)), manualNodeAppendText) + .collections, + ); + //添加工作流 + const workFlowName = faker.string.alphanumeric(5) + triggerNodeAppendText; + const workflowData = { + current: true, + options: { deleteExecutionOnStatus: [] }, + title: workFlowName, + type: 'collection', + enabled: true, + }; + const workflow = await apiCreateWorkflow(workflowData); + const workflowObj = JSON.parse(JSON.stringify(workflow)); + const workflowId = workflowObj.id; + //配置工作流触发器 + const triggerNodeData = { + config: { appends: [], collection: triggerNodeCollectionName, changed: [], condition: { $and: [] }, mode: 1 }, + }; + const triggerNode = await apiUpdateWorkflowTrigger(workflowId, triggerNodeData); + const triggerNodeObj = JSON.parse(JSON.stringify(triggerNode)); + //配置Manual节点 + await page.goto(`admin/workflow/workflows/${workflowId}`); + await page.waitForLoadState('networkidle'); + const collectionTriggerNode = new CollectionTriggerNode(page, workFlowName, triggerNodeCollectionName); + await collectionTriggerNode.addNodeButton.click(); + await page.getByRole('button', { name: 'manual', exact: true }).click(); + const manualNodeName = 'Manual' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Manual-Manual', { exact: true }).getByRole('textbox').fill(manualNodeName); + const manualNode = new ManualNode(page, manualNodeName); + const manualNodeId = await manualNode.node.locator('.workflow-node-id').innerText(); + await manualNode.nodeConfigure.click(); + await manualNode.assigneesDropDown.click(); + await page.getByRole('option', { name: 'Super Admin' }).click(); + await manualNode.configureUserInterfaceButton.click(); + await manualNode.addBlockButton.hover(); + await manualNode.createRecordFormMenu.hover(); + await page.getByRole('menuitem', { name: manualNodeCollectionDisplayName }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByLabel(`designer-schema-settings-CardItem-CreateFormDesigner-${manualNodeCollectionName}`).hover(); + await page.getByRole('menuitem', { name: 'Edit block title' }).click(); + const blockTitle = 'Create record' + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page.getByLabel('Edit block title').getByRole('textbox').fill(blockTitle); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page + .locator(`button[aria-label^="schema-initializer-Grid-FormItemInitializers-${manualNodeCollectionName}"]`) + .hover(); + await page.getByRole('menuitem', { name: manualNodeFieldDisplayName }).getByRole('switch').click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.mouse.click(300, 0); + await manualNode.submitButton.click(); + await page.waitForLoadState('networkidle'); + + // 2、测试步骤:添加数据触发工作流 + const triggerNodeCollectionRecordOne = triggerNodeFieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + const triggerNodeCollectionRecords = await mockRecords(triggerNodeCollectionName, [ + { orgname: triggerNodeCollectionRecordOne }, + ]); + await page.waitForTimeout(1000); + // 3、预期结果:工作流成功触发,待办弹窗表单中显示数据 + const getWorkflow = await apiGetWorkflow(workflowId); + const getWorkflowObj = JSON.parse(JSON.stringify(getWorkflow)); + const getWorkflowExecuted = getWorkflowObj.executed; + expect(getWorkflowExecuted).toBe(1); + + const newPage = mockPage(); + await newPage.goto(); + await page.waitForLoadState('networkidle'); + await page.getByLabel('schema-initializer-Grid-BlockInitializers').hover(); + await page.getByRole('menuitem', { name: 'check-square Workflow todos' }).click(); + await page.mouse.move(300, 0, { steps: 100 }); + await page.waitForTimeout(300); + await page.getByLabel('action-Filter.Action-Filter-filter-users_jobs-workflow-todo').click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'Workflow right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'Name' }).click(); + await page.getByRole('textbox').fill(workFlowName); + await page.getByRole('button', { name: 'Submit' }).click(); + + // 3、预期结果:列表中出现筛选的工作流 + await expect(page.getByText(manualNodeName)).toBeAttached(); + + // 4、后置处理:删除工作流 + await apiDeleteWorkflow(workflowId); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts index d8d54754e..0b1521ac1 100644 --- a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts +++ b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2ePageObjectModel.ts @@ -435,11 +435,11 @@ export class ManualNode { this.assigneesDropDown = page.getByTestId('select-single'); this.configureUserInterfaceButton = page.getByRole('button', { name: 'Configure user interface' }); this.addBlockButton = page.getByLabel('schema-initializer-Grid-AddBlockButton-workflows'); - this.triggerDataMenu = page.getByLabel('Data blocks-triggerData'); - this.nodeDataMenu = page.getByLabel('nodes', { exact: true }); + this.triggerDataMenu = page.getByRole('menuitem', { name: 'Trigger data' }); + this.nodeDataMenu = page.getByRole('menuitem', { name: 'Node result right' }); this.customFormMenu = page.getByRole('menuitem', { name: 'Custom form' }); - this.createRecordFormMenu = page.getByRole('menuitem', { name: 'Create record form' }); - this.updateRecordFormMenu = page.getByRole('menuitem', { name: 'Update record form' }); + this.createRecordFormMenu = page.getByRole('menuitem', { name: 'Create record form right' }); + this.updateRecordFormMenu = page.getByRole('menuitem', { name: 'Update record form right' }); this.submitButton = page.getByLabel('action-Action-Submit-workflows'); this.cancelButton = page.getByLabel('action-Action-Cancel-workflows'); this.addNodeButton = page.getByLabel(`add-button-manual-${nodeName}`, { exact: true }); diff --git a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts index 61159ae68..debedba5e 100644 --- a/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts +++ b/packages/plugins/@nocobase/plugin-workflow-test/src/e2e/e2eUtils.ts @@ -605,6 +605,44 @@ export const apiGetList = async (collectionName: string) => { return await result.json(); }; +// 查询业务表list +export const apiFilterList = async (collectionName: string, filter: string) => { + const api = await request.newContext({ + storageState: process.env.PLAYWRIGHT_AUTH_FILE, + }); + const state = await api.storageState(); + const headers = getHeaders(state); + const result = await api.get(`/api/${collectionName}:list?${filter}`, { + headers, + }); + + if (!result.ok()) { + throw new Error(await result.text()); + } + /* + { + "data": [ + { + "id": 1, + "createdAt": "2023-12-12T02:43:53.793Z", + "updatedAt": "2023-12-12T05:41:33.300Z", + "key": "fzk3j2oj4el", + "title": "a11", + "enabled": true, + "description": null + } + ], + "meta": { + "count": 1, + "page": 1, + "pageSize": 20, + "totalPage": 1 + } + } + */ + return await result.json(); +}; + // 添加业务表单条数据触发工作流表单事件,triggerWorkflows=key1!field,key2,key3!field.subfield export const apiCreateRecordTriggerFormEvent = async (collectionName: string, triggerWorkflows: string, data: any) => { const api = await request.newContext({ @@ -744,4 +782,5 @@ export default module.exports = { apiGetList, apiCreateRecordTriggerFormEvent, apiSubmitRecordTriggerFormEvent, + apiFilterList, };