From ef1b07e6a300ece0a1b1edfce14a5d59f9875e4c Mon Sep 17 00:00:00 2001 From: hongboji Date: Wed, 11 Oct 2023 12:18:35 +0800 Subject: [PATCH 1/2] =?UTF-8?q?test:=20=E7=A1=AE=E8=AE=A4e2e=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B=E5=8F=AF=E8=A1=8C=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/e2e/createLocalStorage.test.ts | 43 + .../__tests__/e2e/editLocalStorage.test.ts | 57 + .../__tests__/e2e/pageobject/localStorage.ts | 49 + .../__tests__/e2e/createFormEvent.test.ts | 36 + .../__tests__/e2e/editFormEvent.test.ts | 43 + .../e2e/pageobject/e2eTemplateJson.ts | 1751 +++++++++++++++++ .../__tests__/e2e/pageobject/workFlow.ts | 43 + .../e2e/triggerCollectionEvent.test.ts | 106 + 8 files changed, 2128 insertions(+) create mode 100644 packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts create mode 100644 packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts create mode 100644 packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/pageobject/localStorage.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/createFormEvent.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/editFormEvent.test.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/e2eTemplateJson.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/workFlow.ts create mode 100644 packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/triggerCollectionEvent.test.ts diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts new file mode 100644 index 000000000..aa93221b4 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts @@ -0,0 +1,43 @@ +import { expect, test } from '@nocobase/test/client'; +import { CreateLocalStorage } from './pageobject/localStorage'; +import { dayjs } from '@nocobase/utils'; + +test.describe('file manager', () => { + test('add new local storage', async ({ page }) => { + //用例编号 + const caseNum = 'FM01AA'; + //用例标题 + const caseTitle = 'add new local storage'; + + // 1、前置条件:已登录 + + // 2、测试步骤:进入“文件管理器”-“新建”按钮,填写表单,点击“确定”按钮 + await page.goto('/admin/settings/file-manager/storages'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('create-action').click(); + const createLocalStorage = new CreateLocalStorage(page); + await createLocalStorage.title.fill(caseTitle); + const storageName = caseNum + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createLocalStorage.storageName.fill(storageName); + await createLocalStorage.storagebaseURL.fill('/storage/uploadsFM01AA'); + await createLocalStorage.storageType.click(); + await page.getByText('Local storage').click(); + await createLocalStorage.destination.fill('storage/uploadsFM01AA'); + // await createLocalStorage.path.fill(''); + // await createLocalStorage.defaultStorage.check(); + // await createLocalStorage.deleteRecordRetentionFile.check(); + await page.getByTestId('submit-action').click(); + + // 3、预期结果:新建成功,列表中出现新建的文件管理器 + await expect(page.getByText(storageName)).toBeAttached(); + // await page.waitForTimeout(5000); + + // 4、后置处理:删除新建的文件管理器 + await page + .getByRole('row', { name: '2 ' + caseTitle + ' ' + storageName + ' Edit Delete' }) + .getByTestId('delete-action') + .click(); + await page.getByRole('button', { name: 'OK' }).click(); + await expect(page.getByText(storageName)).toBeHidden(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts new file mode 100644 index 000000000..4e225cfc3 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts @@ -0,0 +1,57 @@ +import { expect, test } from '@nocobase/test/client'; +import { CreateLocalStorage, EditLocalStorage } from './pageobject/localStorage'; +import { dayjs } from '@nocobase/utils'; + +test.describe('File manager', () => { + test('edit local storage title', async ({ page }) => { + //用例编号 + const caseNum = 'FM02AA'; + //用例标题 + let caseTitle = 'edit local storage title'; + + // 1、前置条件:1.1已登录;1.2存在一个文件管理器 + await page.goto('/admin/settings/file-manager/storages'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('create-action').click(); + + const createLocalStorage = new CreateLocalStorage(page); + await createLocalStorage.title.fill(caseTitle); + const storageName = caseNum + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createLocalStorage.storageName.fill(storageName); + await createLocalStorage.storagebaseURL.fill('/storage/uploadsFM02AA'); + await createLocalStorage.storageType.click(); + await page.getByText('Local storage').click(); + await createLocalStorage.destination.fill('storage/uploadsFM02AA'); + // await createLocalStorage.path.fill(''); + // await createLocalStorage.defaultStorage.check(); + // await createLocalStorage.deleteRecordRetentionFile.check(); + await page.getByTestId('submit-action').click(); + await expect(page.getByText(storageName)).toBeAttached(); + await page.waitForTimeout(5000); + + // 2、测试步骤:点击“文件管理器”-“编辑”按钮,编辑标题,点击“确定”按钮 + await page + .getByRole('row', { name: '2 ' + caseTitle + ' ' + storageName + ' Edit Delete' }) + .getByTestId('update-action') + .click(); + const editLocalStorage = new EditLocalStorage(page); + caseTitle = caseTitle + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await editLocalStorage.title.fill(caseTitle); + // await editLocalStorage.path.fill(''); + // await editLocalStorage.defaultStorage.check(); + // await editLocalStorage.deleteRecordRetentionFile.check(); + await page.getByTestId('submit-action').click(); + // await page.waitForTimeout(5000); + + // 3、预期结果:编辑成功,列表中出现编辑后的文件管理器 + await expect(page.getByText(caseTitle)).toBeAttached(); + + // 4、后置处理:删除文件管理器 + await page + .getByRole('row', { name: '2 ' + caseTitle + ' ' + storageName + ' Edit Delete' }) + .getByTestId('delete-action') + .click(); + await page.getByRole('button', { name: 'OK' }).click(); + await expect(page.getByText(storageName)).toBeHidden(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/pageobject/localStorage.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/pageobject/localStorage.ts new file mode 100644 index 000000000..8d3f99126 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/pageobject/localStorage.ts @@ -0,0 +1,49 @@ +import type { Page, Locator } from '@nocobase/test/client'; + +export class CreateLocalStorage { + readonly page: Page; + title: Locator; + storageName: Locator; + storagebaseURL: Locator; + storageType: Locator; + destination: Locator; + path: Locator; + defaultStorage: Locator; + deleteRecordRetentionFile: Locator; + + constructor(page: Page) { + this.page = page; + this.title = page.getByTestId('title-item').getByRole('textbox'); + this.storageName = page.getByTestId('name-item').getByRole('textbox'); + this.storagebaseURL = page.getByTestId('baseUrl-item').getByRole('textbox'); + this.storageType = page.getByTestId('type-item').getByLabel('Search'); + this.destination = page.getByTestId('documentRoot-item').getByRole('textbox'); + this.path = page.getByTestId('path-item').getByRole('textbox'); + this.defaultStorage = page.getByLabel('Default storage'); + this.deleteRecordRetentionFile = page.getByLabel('Keep file in storage when destroy record'); + } +} + +export class EditLocalStorage { + readonly page: Page; + title: Locator; + storageName: Locator; + storagebaseURL: Locator; + storageType: Locator; + destination: Locator; + path: Locator; + defaultStorage: Locator; + deleteRecordRetentionFile: Locator; + + constructor(page: Page) { + this.page = page; + this.title = page.getByTestId('title-item').getByRole('textbox'); + this.storageName = page.getByTestId('name-item').getByRole('textbox'); + this.storagebaseURL = page.getByTestId('baseUrl-item').getByRole('textbox'); + this.storageType = page.getByTestId('type-item').getByLabel('Search'); + this.destination = page.getByTestId('documentRoot-item').getByRole('textbox'); + this.path = page.getByTestId('path-item').getByRole('textbox'); + this.defaultStorage = page.getByLabel('Default storage'); + this.deleteRecordRetentionFile = page.getByLabel('Keep file in storage when destroy record'); + } +} diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/createFormEvent.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/createFormEvent.test.ts new file mode 100644 index 000000000..ae355b0ff --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/createFormEvent.test.ts @@ -0,0 +1,36 @@ +import { expect, test } from '@nocobase/test/client'; +import { dayjs } from '@nocobase/utils'; +import { CreateWorkFlow } from './pageobject/workFlow'; + +test.describe('workflow manage', () => { + test('add new from event', async ({ page }) => { + //用例编号 + const caseNum = 'WF02AA'; + //用例标题 + const caseTitle = 'add new from event'; + + // 1、前置条件:已登录 + + // 2、测试步骤:进入“工作流管理”-“新建”按钮,填写表单,点击“确定”按钮 + await page.goto('/admin/settings/workflow/workflows'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('create-action').click(); + const createWorkFlow = new CreateWorkFlow(page); + const workFlowName = caseTitle + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createWorkFlow.name.fill(workFlowName); + await createWorkFlow.triggerType.click(); + await page.getByText('Form event').click(); + await page.getByTestId('submit-action').click(); + + // 3、预期结果:新建成功,列表中出现新建的工作流 + await expect(page.getByText(workFlowName)).toBeAttached(); + + // 4、后置处理:删除新建的工作流 + await page.getByTestId('filter-action').click(); + await page.getByRole('textbox').fill(workFlowName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('cell', { name: 'View Edit Duplicate Delete' }).getByTestId('delete-action').click(); + await page.getByRole('button', { name: 'OK' }).click(); + await expect(page.getByText(workFlowName)).toBeHidden(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/editFormEvent.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/editFormEvent.test.ts new file mode 100644 index 000000000..6ca9fc93a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/editFormEvent.test.ts @@ -0,0 +1,43 @@ +import { expect, test } from '@nocobase/test/client'; +import { CreateWorkFlow, EditWorkFlow } from './pageobject/workFlow'; +import { dayjs } from '@nocobase/utils'; + +test.describe('workflow manage', () => { + test('edit from event name', async ({ page }) => { + //用例编号 + const caseNum = 'WF05AA'; + //用例标题 + const caseTitle = 'edit from event name'; + + // 1、前置条件:1.1、已登录,1.2、存在一个工作流 + await page.goto('/admin/settings/workflow/workflows'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('create-action').click(); + const createWorkFlow = new CreateWorkFlow(page); + let workFlowName = caseTitle + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createWorkFlow.name.fill(workFlowName); + await createWorkFlow.triggerType.click(); + await page.getByText('Form event').click(); + await page.getByTestId('submit-action').click(); + + await expect(page.getByText(workFlowName)).toBeAttached(); + + // 2、测试步骤:进入“工作流管理”-“编辑”按钮,编辑名称,点击“确定”按钮 + await page.getByTestId('update-action').click(); + const editWorkFlow = new EditWorkFlow(page); + workFlowName = caseTitle + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createWorkFlow.name.fill(workFlowName); + await page.getByTestId('submit-action').click(); + + // 3、预期结果:编辑成功,列表中出现编辑后的工作流 + await expect(page.getByText(workFlowName)).toBeAttached(); + + // 4、后置处理:删除工作流 + await page.getByTestId('filter-action').click(); + await page.getByRole('textbox').fill(workFlowName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('cell', { name: 'View Edit Duplicate Delete' }).getByTestId('delete-action').click(); + await page.getByRole('button', { name: 'OK' }).click(); + await expect(page.getByText(workFlowName)).toBeHidden(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/e2eTemplateJson.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/e2eTemplateJson.ts new file mode 100644 index 000000000..8f82d5a73 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/e2eTemplateJson.ts @@ -0,0 +1,1751 @@ +import { dayjs } from '@nocobase/utils'; +import { lowerCase } from 'lodash'; + +/** + * 为json对象中collections节点的name、title属性添加后缀 + * 为json对象中fields节点的collectionName、through、target性添加后缀 + * @param jsonObj json对象 + * @param appendText 后缀文本 + */ +export function appendJsonCollectionName(jsonObj: any, appendText: string) { + appendCollectionsNode(jsonObj, appendText); + for (const item of jsonObj['collections'][0]['fields']) { + appendFieldsNode(item, appendText); + } + return jsonObj; +} + +function appendCollectionsNode(jsonObj: any, appendText: string) { + jsonObj['collections'][0]['name'] += appendText; + jsonObj['collections'][0]['title'] += appendText; +} +function appendFieldsNode(jsonObj: any, appendText: string) { + for (const key in jsonObj) { + if (key === 'collectionName' || key === 'through' || key === 'target') { + jsonObj[key] += appendText; + } + } +} +/** + * @returns 生成3位随机小写字母 + */ +export function generateRandomLetters() { + let result = ''; + const characters = 'abcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < 3; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} +/** + * builtin_ 为NocoBase内置模板,同NocoBase在页面创建效果一致主要用法3种: + * 1是测试用例仅需一个无业务字段的表即可验证, + * 2是作为多对多的中间表, + * 3是存在先表后关系字段的情况,使用create内置模板表再update表的方式更新数据表来添加全部字段 + * e2e_ 按照不同场景的数据表,可以多个测试用例共用一个或一套数据表 + */ +export const builtin_General = { + collections: [ + { + key: 'hqh4qy21m46', + name: 'tt_amt_org', + title: '自动>组织[普通表]', + inherit: false, + hidden: false, + description: null, + fields: [ + { + key: 'z3fvals50xp', + name: 'id', + type: 'bigInt', + interface: 'id', + description: null, + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: '3cp1zy4ogle', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + description: null, + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: '6l38n4nt7nb', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + description: null, + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: '3xds0p7ersr', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + description: null, + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'slqyx974mzc', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + description: null, + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + ], + category: [], + logging: true, + autoGenId: true, + createdBy: true, + updatedBy: true, + createdAt: true, + updatedAt: true, + sortable: true, + template: 'general', + view: false, + schema: 'public', + }, + ], +}; +export const builtin_Calendar = { + collections: [ + { + key: '7lfgblnyr0w', + name: 'tt_amt_org_cld', + title: '自动>组织[日历表]', + inherit: false, + hidden: false, + description: null, + fields: [ + { + key: 'nq6a40fz0nd', + name: 'cron', + type: 'string', + interface: 'select', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + title: '{{t("Repeats")}}', + 'x-component': 'CronSet', + 'x-component-props': 'allowClear', + enum: [ + { + label: '{{t("Daily")}}', + value: '0 0 0 * * ?', + }, + { + label: '{{t("Weekly")}}', + value: 'every_week', + }, + { + label: '{{t("Monthly")}}', + value: 'every_month', + }, + { + label: '{{t("Yearly")}}', + value: 'every_year', + }, + ], + }, + }, + { + key: 'qtxt638o4nq', + name: 'exclude', + type: 'json', + interface: null, + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + }, + { + key: 'ly88an4fg8f', + name: 'id', + type: 'bigInt', + interface: 'id', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: '8fiqtpovg79', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'hup33jdnp9j', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: '4ky6wvfhduq', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: '1xht59blk26', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + description: null, + collectionName: 'tt_amt_org_cld', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + ], + category: [], + logging: true, + template: 'calendar', + view: false, + createdBy: true, + updatedBy: true, + createdAt: true, + updatedAt: true, + sortable: true, + schema: 'public', + }, + ], +}; +export const builtin_Tree = { + collections: [ + { + key: 'wvgsufr1uxv', + name: 'tt_amt_org_tree', + title: '自动>组织[树表]', + inherit: false, + hidden: false, + description: null, + fields: [ + { + key: '4ihc87rzn00', + name: 'parentId', + type: 'bigInt', + interface: 'integer', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + isForeignKey: true, + uiSchema: { + type: 'number', + title: '{{t("Parent ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + target: 'tt_amt_org_tree', + }, + { + key: 'j58bfihyjdy', + name: 'parent', + type: 'belongsTo', + interface: 'm2o', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + foreignKey: 'parentId', + treeParent: true, + onDelete: 'CASCADE', + uiSchema: { + title: '{{t("Parent")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + multiple: false, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + }, + target: 'tt_amt_org_tree', + targetKey: 'id', + }, + { + key: '6r6b98g0hcz', + name: 'children', + type: 'hasMany', + interface: 'o2m', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + foreignKey: 'parentId', + treeChildren: true, + onDelete: 'CASCADE', + uiSchema: { + title: '{{t("Children")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + multiple: true, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + }, + target: 'tt_amt_org_tree', + targetKey: 'id', + sourceKey: 'id', + }, + { + key: 'hju1ggqps4n', + name: 'id', + type: 'bigInt', + interface: 'id', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: '1y7rpmh8muj', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'ieknujjdkv9', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: 'cv35rzoqna6', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'z21wfpry7uh', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + description: null, + collectionName: 'tt_amt_org_tree', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + ], + category: [], + logging: true, + autoGenId: true, + createdBy: true, + updatedBy: true, + createdAt: true, + updatedAt: true, + sortable: true, + template: 'tree', + view: false, + tree: 'adjacencyList', + schema: 'public', + }, + ], +}; +export const builtin_File = { + collections: [ + { + key: '6hzed4cvpxo', + name: 'tt_amt_file', + title: '自动>档案[文件表]', + inherit: false, + hidden: false, + description: null, + fields: [ + { + key: 'qo0w8dcl45u', + name: 'title', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("Title")}}', + 'x-component': 'Input', + }, + }, + { + key: 'ayzc9b3aee5', + name: 'filename', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("File name", { ns: "file-manager" })}}', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, + { + key: 'ftn60zv1rfr', + name: 'extname', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("Extension name", { ns: "file-manager" })}}', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, + { + key: '59oj6m0r8be', + name: 'size', + type: 'integer', + interface: 'integer', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'number', + title: '{{t("Size", { ns: "file-manager" })}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + 'x-component-props': { + stringMode: true, + step: '0', + }, + }, + }, + { + key: 'burt1tfbcjx', + name: 'mimetype', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("Mime type", { ns: "file-manager" })}}', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, + { + key: '1zfhbqod0i1', + name: 'path', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("Path")}}', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, + { + key: 'b0bmsmrfqqw', + name: 'url', + type: 'string', + interface: 'input', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("URL")}}', + 'x-component': 'Input.URL', + 'x-read-pretty': true, + }, + }, + { + key: 'indgsp9sqqq', + name: 'preview', + type: 'string', + interface: 'url', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + field: 'url', + deletable: false, + uiSchema: { + type: 'string', + title: '{{t("Preview")}}', + 'x-component': 'Preview', + 'x-read-pretty': true, + }, + }, + { + key: '2p8d1h46x9l', + name: 'storage', + type: 'belongsTo', + interface: null, + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + comment: '存储引擎', + target: 'storages', + foreignKey: 'storageId', + deletable: false, + targetKey: 'id', + }, + { + key: 'im0yegvb5jt', + name: 'meta', + type: 'jsonb', + interface: null, + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + deletable: false, + defaultValue: {}, + }, + { + key: 'tjr9nr5thoh', + name: 'id', + type: 'bigInt', + interface: 'id', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: 's48vjiqbjcq', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'y3t7jii4m8w', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: 'z5gvejdbfyb', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'qgd8zko7b0z', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + description: null, + collectionName: 'tt_amt_file', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + ], + category: [], + logging: true, + template: 'file', + view: false, + createdBy: true, + updatedBy: true, + storage: 'local', + schema: 'public', + }, + ], +}; +export const builtin_Expression = { + collections: [ + { + key: 'w77iro3197g', + name: 'tt_amt_exp', + title: '自动>表达式[表达式表]', + inherit: false, + hidden: false, + description: null, + fields: [ + { + key: 'slc2i7yz2ck', + name: 'engine', + type: 'string', + interface: 'radioGroup', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + title: '{{t("Calculation engine")}}', + 'x-component': 'Radio.Group', + enum: [ + { + value: 'math.js', + label: 'Math.js', + tooltip: + "{{t('Math.js comes with a large set of built-in functions and constants, and offers an integrated solution to work with different data types')}}", + link: 'https://mathjs.org/', + }, + { + value: 'formula.js', + label: 'Formula.js', + tooltip: '{{t("Formula.js supports most Microsoft Excel formula functions.")}}', + link: 'https://formulajs.info/functions/', + }, + ], + default: 'formula.js', + }, + }, + { + key: 'mlvkdcg2yvq', + name: 'sourceCollection', + type: 'string', + interface: 'select', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + title: '{{t("Collection")}}', + 'x-component': 'CollectionSelect', + 'x-component-props': {}, + }, + }, + { + key: 'vdzigakt9ne', + name: 'expression', + type: 'text', + interface: 'expression', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + title: '{{t("Expression")}}', + 'x-component': 'DynamicExpression', + }, + }, + { + key: 'fx72pqt0fjv', + name: 'id', + type: 'bigInt', + interface: 'id', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: 'owiio66cw1u', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: '9fu8kmc69dj', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: 'uie8q16z2jj', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: '6jzyuc1jzro', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + description: null, + collectionName: 'tt_amt_exp', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'RecordPicker', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + ], + category: [], + logging: true, + template: 'expression', + view: false, + createdBy: true, + updatedBy: true, + createdAt: true, + updatedAt: true, + sortable: true, + schema: 'public', + }, + ], +}; +//普通表单表场景,无关系字段情况 +export const e2e_GeneralFormsTable = { + collections: [ + { + key: '86lpobjxamt', + name: 'tt_amt_org', + title: '自动>组织[普通表]', + inherit: false, + hidden: false, + fields: [ + { + key: 'ohxa8xp9amt', + name: 'id', + type: 'bigInt', + interface: 'id', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + autoIncrement: true, + primaryKey: true, + allowNull: false, + uiSchema: { + type: 'number', + title: '{{t("ID")}}', + 'x-component': 'InputNumber', + 'x-read-pretty': true, + }, + }, + { + key: 'qjit9pcvamt', + name: 'createdAt', + type: 'date', + interface: 'createdAt', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + field: 'createdAt', + uiSchema: { + type: 'datetime', + title: '{{t("Created at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'vijs3wcnamt', + name: 'createdBy', + type: 'belongsTo', + interface: 'createdBy', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'createdById', + uiSchema: { + type: 'object', + title: '{{t("Created by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: 'zsebjtwiamt', + name: 'updatedAt', + type: 'date', + interface: 'updatedAt', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + field: 'updatedAt', + uiSchema: { + type: 'string', + title: '{{t("Last updated at")}}', + 'x-component': 'DatePicker', + 'x-component-props': {}, + 'x-read-pretty': true, + }, + }, + { + key: 'fa4c74phamt', + name: 'updatedBy', + type: 'belongsTo', + interface: 'updatedBy', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + target: 'users', + foreignKey: 'updatedById', + uiSchema: { + type: 'object', + title: '{{t("Last updated by")}}', + 'x-component': 'AssociationField', + 'x-component-props': { + fieldNames: { + value: 'id', + label: 'nickname', + }, + }, + 'x-read-pretty': true, + }, + targetKey: 'id', + }, + { + key: 'mv6h7f8lamt', + name: 'orgcode', + type: 'sequence', + interface: 'sequence', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + patterns: [ + { + type: 'string', + options: { + value: '区域编码', + }, + }, + { + type: 'integer', + options: { + digits: 9, + start: 1, + key: 57450, + }, + }, + ], + uiSchema: { + type: 'string', + 'x-component': 'Input', + 'x-component-props': {}, + title: '公司编号(自动编码)', + }, + inputable: false, + }, + { + key: '44u5zoyyamt', + name: 'orgname', + type: 'string', + interface: 'input', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'Input', + title: '公司名称(单行文本)', + }, + }, + { + key: 'tdq82bb0amt', + name: 'address', + type: 'text', + interface: 'textarea', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'Input.TextArea', + title: '公司地址(多行文本)', + }, + }, + { + key: '10xi6i24amt', + name: 'phone', + type: 'string', + interface: 'phone', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'Input', + 'x-component-props': { + type: 'tel', + }, + title: '负责人电话(手机号码)', + }, + }, + { + key: 'n3ykqhe4amt', + name: 'email', + type: 'string', + interface: 'email', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'Input', + 'x-validator': 'email', + title: '电子邮箱(电子邮箱)', + }, + }, + { + key: '5ddcgbpqamt', + name: 'staffnum', + type: 'bigInt', + interface: 'integer', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'number', + 'x-component': 'InputNumber', + 'x-component-props': { + stringMode: true, + step: '1', + }, + 'x-validator': 'integer', + title: '员工人数(整数)', + }, + }, + { + key: 'z59sf4ilamt', + name: 'insurednum', + type: 'bigInt', + interface: 'integer', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'number', + 'x-component': 'InputNumber', + 'x-component-props': { + stringMode: true, + step: '1', + }, + 'x-validator': 'integer', + title: '参保人数(整数)', + }, + }, + { + key: 'ecvb3a8xamt', + name: 'regcapital', + type: 'double', + interface: 'number', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + 'x-component-props': { + step: '0.0001', + stringMode: true, + }, + type: 'number', + 'x-component': 'InputNumber', + title: '注册资本(数字)', + }, + }, + { + key: 'ierg1fbvamt', + name: 'paidcapital', + type: 'double', + interface: 'number', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + 'x-component-props': { + step: '0.0001', + stringMode: true, + }, + type: 'number', + 'x-component': 'InputNumber', + title: '实缴资本(数字)', + }, + }, + { + key: '46kjnywaamt', + name: 'insuranceratio', + type: 'float', + interface: 'percent', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + 'x-component-props': { + step: '0.01', + stringMode: true, + addonAfter: '%', + }, + type: 'string', + 'x-component': 'Percent', + title: '参保占比(百分比)', + }, + }, + { + key: '8j2vkys9amt', + name: 'isenable', + type: 'boolean', + interface: 'checkbox', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'boolean', + 'x-component': 'Checkbox', + title: '是否启用(勾选)', + }, + }, + { + key: '6f480de5amt', + name: 'status_singleselect', + type: 'string', + interface: 'select', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + enum: [ + { + value: '1', + label: '存续', + }, + { + value: '2', + label: '在业', + }, + { + value: '3', + label: '吊销', + }, + { + value: '4', + label: '注销', + }, + { + value: '5', + label: '迁入', + }, + { + value: '6', + label: '迁出', + }, + { + value: '7', + label: '停业', + }, + { + value: '8', + label: '清算', + }, + ], + type: 'string', + 'x-component': 'Select', + title: '公司状态(下拉单选)', + }, + }, + { + key: 'fcx8cw1ramt', + name: 'range_multipleselect', + type: 'array', + interface: 'multipleSelect', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + enum: [ + { + value: 'F3134', + label: '软件销售', + }, + { + value: 'I3006', + label: '软件开发', + }, + { + value: 'I3007', + label: '人工智能基础软件开发', + }, + { + value: 'I3008', + label: '人工智能应用软件开发', + }, + { + value: 'I3010', + label: '软件外包服务', + }, + { + value: 'I3011', + label: '网络与信息安全软件开发', + }, + { + value: 'I3012', + label: '人工智能理论与算法软件开发', + }, + { + value: 'I3014', + label: '数字文化创意软件开发', + }, + { + value: 'I3027', + label: '信息技术咨询服务', + }, + { + value: 'I3032', + label: '数据处理服务', + }, + { + value: 'I3034', + label: '计算机系统服务', + }, + { + value: 'L2032', + label: '信息咨询服务(不含许可类信息咨询服务)', + }, + { + value: 'L2095', + label: '企业管理咨询', + }, + { + value: 'M2070', + label: '技术服务、技术开发、技术咨询、技术交流、技术转让、技术推广', + }, + { + value: 'O3010', + label: '咨询策划服务', + }, + { + value: 'P1029', + label: '业务培训(不含教育培训、职业技能培训等需取得许可的培训)', + }, + ], + type: 'array', + 'x-component': 'Select', + 'x-component-props': { + mode: 'multiple', + }, + title: '经营范围(下拉多选)', + }, + defaultValue: [], + }, + { + key: 'z71al7aaamt', + name: 'status_radio', + type: 'string', + interface: 'radioGroup', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + enum: [ + { + value: '1', + label: '存续', + }, + { + value: '2', + label: '在业', + }, + { + value: '3', + label: '吊销', + }, + { + value: '4', + label: '注销', + }, + { + value: '5', + label: '迁入', + }, + { + value: '6', + label: '迁出', + }, + { + value: '7', + label: '停业', + }, + { + value: '8', + label: '清算', + }, + ], + type: 'string', + 'x-component': 'Radio.Group', + title: '公司状态(单选)', + }, + }, + { + key: 'x8v9qf95amt', + name: 'range_check', + type: 'array', + interface: 'checkboxGroup', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + enum: [ + { + value: 'F3134', + label: '软件销售', + }, + { + value: 'I3006', + label: '软件开发', + }, + { + value: 'I3007', + label: '人工智能基础软件开发', + }, + { + value: 'I3008', + label: '人工智能应用软件开发', + }, + { + value: 'I3010', + label: '软件外包服务', + }, + { + value: 'I3011', + label: '网络与信息安全软件开发', + }, + { + value: 'I3012', + label: '人工智能理论与算法软件开发', + }, + { + value: 'I3014', + label: '数字文化创意软件开发', + }, + { + value: 'I3027', + label: '信息技术咨询服务', + }, + { + value: 'I3032', + label: '数据处理服务', + }, + { + value: 'I3034', + label: '计算机系统服务', + }, + { + value: 'L2032', + label: '信息咨询服务(不含许可类信息咨询服务)', + }, + { + value: 'L2095', + label: '企业管理咨询', + }, + { + value: 'M2070', + label: '技术服务、技术开发、技术咨询、技术交流、技术转让、技术推广', + }, + { + value: 'O3010', + label: '咨询策划服务', + }, + { + value: 'P1029', + label: '业务培训(不含教育培训、职业技能培训等需取得许可的培训)', + }, + ], + type: 'string', + 'x-component': 'Checkbox.Group', + title: '经营范围(复选)', + }, + defaultValue: [], + }, + { + key: 'c50l1zguamt', + name: 'range_markdown', + type: 'text', + interface: 'markdown', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'Markdown', + title: '经营范围(Markdown)', + }, + }, + { + key: 'msj1qa4damt', + name: 'range_richtext', + type: 'text', + interface: 'richText', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + 'x-component': 'RichText', + title: '经营范围(富文本)', + }, + }, + { + key: 'q755hkxmamt', + name: 'establishdate', + type: 'date', + interface: 'datetime', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + 'x-component-props': { + dateFormat: 'YYYY-MM-DD', + gmt: false, + showTime: false, + }, + type: 'string', + 'x-component': 'DatePicker', + title: '成立日期(日期)', + }, + }, + { + key: '9kn4ujeramt', + name: 'range_json', + type: 'json', + interface: 'json', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + defaultValue: null, + uiSchema: { + type: 'object', + 'x-component': 'Input.JSON', + 'x-component-props': { + autoSize: { + minRows: 5, + }, + }, + default: null, + title: '经营范围(JSON)', + }, + }, + { + key: 'vqcsj7htamt', + name: 'url', + type: 'string', + interface: 'url', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'string', + title: '官网地址(URL)', + 'x-component': 'Input.URL', + }, + }, + { + key: '0naiw2nq4j0', + name: 'insuranceratio_formula', + type: 'formula', + interface: 'formula', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + dataType: 'double', + uiSchema: { + 'x-component-props': { + step: '0.01', + stringMode: true, + }, + type: 'number', + 'x-component': 'Formula.Result', + 'x-read-pretty': true, + title: '参保占比(公式)', + }, + engine: 'math.js', + expression: '100*{{insurednum}}/{{staffnum}}', + }, + { + key: 'fd9sqp8usoj', + name: 'sharesnum', + type: 'bigInt', + interface: 'integer', + collectionName: 'tt_amt_org', + parentKey: null, + reverseKey: null, + uiSchema: { + type: 'number', + 'x-component': 'InputNumber', + 'x-component-props': { + stringMode: true, + step: '1', + }, + 'x-validator': 'integer', + title: '股票数量(整数)', + }, + }, + ], + category: [], + logging: true, + autoGenId: true, + createdBy: true, + updatedBy: true, + createdAt: true, + updatedAt: true, + sortable: true, + template: 'general', + }, + ], +}; + +export default module.exports = { + appendJsonCollectionName, + builtin_General, + builtin_File, + builtin_Expression, + e2e_GeneralFormsTable, + generateRandomLetters, +}; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/workFlow.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/workFlow.ts new file mode 100644 index 000000000..9bcc6f2a6 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/pageobject/workFlow.ts @@ -0,0 +1,43 @@ +import type { Page, Locator } from '@nocobase/test/client'; + +export class CreateWorkFlow { + readonly page: Page; + name: Locator; + triggerType: Locator; + description: Locator; + autoDeleteHistory: Locator; + + constructor(page: Page) { + this.page = page; + this.name = page.getByTestId('title-item').getByRole('textbox'); + this.triggerType = page.getByTestId('type-item').getByLabel('Search'); + this.description = page.getByTestId('description-item').getByRole('textbox'); + this.autoDeleteHistory = page + .getByTestId('deleteExecutionOnStatus-item') + .getByTestId('antd-select') + .locator('div') + .nth(1); + } +} + +export class EditWorkFlow { + readonly page: Page; + name: Locator; + statusIsOn: Locator; + statusIisOff: Locator; + description: Locator; + autoDeleteHistory: Locator; + + constructor(page: Page) { + this.page = page; + this.name = page.getByTestId('title-item').getByRole('textbox'); + this.statusIsOn = page.getByTestId('enabled-item').getByLabel('On'); + this.statusIisOff = page.getByLabel('Off'); + this.description = page.getByTestId('description-item').getByRole('textbox'); + this.autoDeleteHistory = page + .getByTestId('deleteExecutionOnStatus-item') + .getByTestId('antd-select') + .locator('div') + .nth(1); + } +} diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/triggerCollectionEvent.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/triggerCollectionEvent.test.ts new file mode 100644 index 000000000..93868260a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/__tests__/e2e/triggerCollectionEvent.test.ts @@ -0,0 +1,106 @@ +import { expect, test } from '@nocobase/test/client'; +import { CreateWorkFlow, EditWorkFlow } from './pageobject/workFlow'; +import { dayjs } from '@nocobase/utils'; +import { e2e_GeneralFormsTable, appendJsonCollectionName, generateRandomLetters } from './pageobject/e2eTemplateJson'; + +test.describe('trigger collection events', () => { + test('add data to trigger collection events', async ({ page, mockPage }) => { + //用例编号 + const caseNum = 'WF20AA'; + //后缀标识,用于不同用例调用e2eTemplateJson.ts中相同模板JSON生成不同的数据表标识、名称 + const appendText = caseNum.toLowerCase() + generateRandomLetters().toString(); + //用例标题 + const caseTitle = 'add data to trigger collection events'; + + // 1、前置条件:1.1、已登录;1.2、存在一个配置好数据表的表单事件工作流;1.3、存在一个添加数据的区块 + //创建数据表 + const e2eJsonCollectionDisplayName = '自动>组织[普通表]'; + const e2eJsonCollectionName = 'tt_amt_org'; + + const collectionDisplayName = e2eJsonCollectionDisplayName + appendText; + const collectionName = e2eJsonCollectionName + appendText; + const fieldName = 'orgname'; + const fieldDisplayName = '公司名称(单行文本)'; + + const newPage = mockPage(appendJsonCollectionName(e2e_GeneralFormsTable, appendText)); + //配置工作流 + await page.goto('/admin/settings/workflow/workflows'); + await page.waitForLoadState('networkidle'); + await page.getByTestId('create-action').click(); + const createWorkFlow = new CreateWorkFlow(page); + const workFlowName = caseTitle + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await createWorkFlow.name.fill(workFlowName); + await createWorkFlow.triggerType.click(); + await page.getByTitle('Collection event').getByText('Collection event').click(); + await page.getByTestId('submit-action').click(); + await expect(page.getByText(workFlowName)).toBeAttached(); + + //配置工作流触发器 + await page + .getByRole('row', { name: '1 ' + workFlowName + ' Collection event Off 0 View Edit Duplicate Delete' }) + .getByRole('link') + .click(); + await page.getByRole('button', { name: 'Configure' }).click(); + await page.getByTestId('antd-select').getByLabel('Search').click(); + await page.getByText('自动>组织[普通表]').click(); + await page.getByTestId('mode-item').getByLabel('Search').click(); + await page.getByText('After record added', { exact: true }).click(); + await page.getByTestId('submit-action').click(); + await page.getByRole('link', { name: 'Workflow' }).click(); + await page + .getByRole('row', { name: '1 ' + workFlowName + ' Collection event Off 0 View Edit Duplicate Delete' }) + .getByTestId('update-action') + .click(); + await page.getByTestId('enabled-item').getByLabel('On').check(); + await page.getByTestId('submit-action').click(); + + //配置录入数据区块 + await newPage.goto(); + await page.getByRole('button', { name: 'plus Add block' }).hover(); + await page.getByRole('menuitem', { name: 'table Table right' }).hover(); + await page.getByRole('menuitem', { name: collectionDisplayName }).click(); + await page.getByRole('button', { name: 'setting Configure columns' }).click(); + await page.getByRole('menuitem', { name: fieldDisplayName }).getByRole('switch').click(); + await page.getByRole('button', { name: 'setting Configure actions' }).hover(); + await page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch').click(); + await expect(page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch')).toBeEnabled(); + await page.getByRole('button', { name: 'setting Configure columns' }).hover(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('Add new').getByRole('button', { name: 'plus Add block' }).hover(); + await page.getByRole('menuitem', { name: 'form Form' }).click(); + await page.getByRole('button', { name: 'plus Add tab' }).click(); + await page.getByRole('button', { name: 'Cancel' }).click(); + await page.getByLabel('Add new').getByRole('button', { name: 'setting Configure actions' }).click(); + await page.getByRole('group').getByText('Submit').click(); + await page.getByRole('button', { name: 'setting Configure fields' }).click(); + await page.getByRole('menuitem', { name: fieldDisplayName }).getByRole('switch').click(); + await page.getByRole('button', { name: 'plus Add tab' }).click(); + await page.getByRole('button', { name: 'Cancel' }).click(); + + // 2、测试步骤:进入“数据区块”-“添加”按钮,填写表单,点击“确定”按钮 + await page + .getByTestId(collectionName + '.' + fieldName + '-field') + .getByRole('textbox') + .click(); + const fieldData = fieldDisplayName + dayjs().format('YYYYMMDDHHmmss.SSS').toString(); + await page + .getByTestId(collectionName + '.' + fieldName + '-field') + .getByRole('textbox') + .fill(fieldData); + await page.getByRole('button', { name: 'Submit' }).click(); + await expect(page.getByText(fieldData)).toBeAttached(); + + // 3、预期结果:数据添加成功,工作流成功触发 + await expect(page.getByText(fieldData)).toBeAttached(); + await page.goto('/admin/settings/workflow/workflows'); + await expect(page.getByRole('table').locator('a').filter({ hasText: '1' })).toBeAttached(); + + // 4、后置处理:删除工作流 + await page.getByTestId('filter-action').click(); + await page.getByRole('textbox').fill(workFlowName); + await page.getByRole('button', { name: 'Submit' }).click(); + await page.getByRole('cell', { name: 'View Edit Duplicate Delete' }).getByTestId('delete-action').click(); + await page.getByRole('button', { name: 'OK' }).click(); + await expect(page.getByText(workFlowName)).toBeHidden(); + }); +}); From 86c4c199f6ac0527871f2af8055a9e2640479556 Mon Sep 17 00:00:00 2001 From: hongboji Date: Wed, 11 Oct 2023 14:56:16 +0800 Subject: [PATCH 2/2] test: revise test cases --- .../src/client/__tests__/e2e/createLocalStorage.test.ts | 2 +- .../src/client/__tests__/e2e/editLocalStorage.test.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts index aa93221b4..214d06831 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/createLocalStorage.test.ts @@ -21,7 +21,7 @@ test.describe('file manager', () => { await createLocalStorage.storageName.fill(storageName); await createLocalStorage.storagebaseURL.fill('/storage/uploadsFM01AA'); await createLocalStorage.storageType.click(); - await page.getByText('Local storage').click(); + await page.getByText('Local storage').nth(1).click(); await createLocalStorage.destination.fill('storage/uploadsFM01AA'); // await createLocalStorage.path.fill(''); // await createLocalStorage.defaultStorage.check(); diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts index 4e225cfc3..28fb78d57 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/client/__tests__/e2e/editLocalStorage.test.ts @@ -20,14 +20,13 @@ test.describe('File manager', () => { await createLocalStorage.storageName.fill(storageName); await createLocalStorage.storagebaseURL.fill('/storage/uploadsFM02AA'); await createLocalStorage.storageType.click(); - await page.getByText('Local storage').click(); + await page.getByText('Local storage').nth(1).click(); await createLocalStorage.destination.fill('storage/uploadsFM02AA'); // await createLocalStorage.path.fill(''); // await createLocalStorage.defaultStorage.check(); // await createLocalStorage.deleteRecordRetentionFile.check(); await page.getByTestId('submit-action').click(); await expect(page.getByText(storageName)).toBeAttached(); - await page.waitForTimeout(5000); // 2、测试步骤:点击“文件管理器”-“编辑”按钮,编辑标题,点击“确定”按钮 await page