From 4121075a986d2da4b562781c992de038330f8ab1 Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Fri, 29 Dec 2023 09:14:47 +0800 Subject: [PATCH] test(e2e): add tests for collection manager (#3253) * refactor: optimize file structure * test: add tests for collection templates * test: fix errors * fix: fix errors * test: schemaInitializer of fields * fix: test erros * fix: test error * test: make tests more stable * test: fix tree template --- .../Configuration/AddCollectionAction.tsx | 4 +- .../Configuration/AddFieldAction.tsx | 6 +- .../Configuration/ConfigurationTabs.tsx | 4 - packages/core/test/src/e2e/e2eUtils.ts | 62 +- .../collection-template/calendar.test.ts | 80 ++ .../connectToDatabaseView.test.ts | 7 + .../collection-template/expression.test.ts | 80 ++ .../__e2e__/collection-template/file.test.ts | 83 ++ .../collection-template/general.test.ts | 263 ++++++ .../__e2e__/collection-template/sql.test.ts | 54 ++ .../__e2e__/collection-template/tree.test.ts | 101 +++ .../attachment/schemaInitializer.test.ts | 67 ++ .../fields/attachment/schemaSettings.test.ts | 285 +++++++ .../belongsTo/schemaInitializer.test.ts | 73 ++ .../fields/belongsTo/schemaSettings.test.ts | 548 +++++++++++++ .../fields/checkbox/schemaInitializer.test.ts | 67 ++ .../fields/checkbox/schemaSettings.test.ts | 241 ++++++ .../checkboxGroup/schemaInitializer.test.ts | 0 .../checkboxGroup/schemaSettings.test.ts | 248 ++++++ .../chinaRegion/schemaInitializer.test.ts | 0 .../fields/chinaRegion/schemaSettings.test.ts | 249 ++++++ .../collection/schemaInitializer.test.ts | 71 ++ .../fields/collection/schemaSettings.test.ts | 91 +++ .../fields/color/schemaInitializer.test.ts | 115 +++ .../fields/color/schemaSettings.test.ts | 239 ++++++ .../createdAt/schemaInitializer.test.ts | 71 ++ .../fields/createdAt/schemaSettings.test.ts | 152 ++++ .../createdBy/schemaInitializer.test.ts | 0 .../fields/createdBy/schemaSettings.test.ts | 138 ++++ .../fields/datetime/schemaInitializer.test.ts | 71 ++ .../fields/datetime/schemaSettings.test.ts | 327 ++++++++ .../fields/email/schemaInitializer.test.ts | 0 .../fields/email/schemaSettings.test.ts | 223 +++++ .../fields/formula/schemaInitializer.test.ts | 0 .../fields/formula/schemaSettings.test.ts | 79 ++ .../fields/hasOne/schemaInitializer.test.ts | 0 .../fields/hasOne/schemaSettings.test.ts | 543 +++++++++++++ .../fields/icon/schemaInitializer.test.ts | 0 .../fields/icon/schemaSettings.test.ts | 201 +++++ .../fields/id/schemaInitializer.test.ts | 0 .../__e2e__/fields/id/schemaSettings.test.ts | 108 +++ .../fields/integer/schemaInitializer.test.ts | 0 .../fields/integer/schemaSettings.test.ts | 284 +++++++ .../fields/json/schemaInitializer.test.ts | 0 .../fields/json/schemaSettings.test.ts | 87 ++ .../lastUpdatedAt/schemaInitializer.test.ts | 0 .../lastUpdatedAt/schemaSettings.test.ts | 93 +++ .../lastUpdatedBy/schemaInitializer.test.ts | 0 .../lastUpdatedBy/schemaSettings.test.ts | 138 ++++ .../fields/longText/schemaInitializer.test.ts | 0 .../fields/longText/schemaSettings.test.ts | 286 +++++++ .../manyToMany/schemaInitializer.test.ts | 0 .../fields/manyToMany/schemaSettings.test.ts | 769 ++++++++++++++++++ .../manyToOne/schemaInitializer.test.ts | 0 .../fields/manyToOne/schemaSettings.test.ts | 639 +++++++++++++++ .../fields/markdown/schemaInitializer.test.ts | 0 .../fields/markdown/schemaSettings.test.ts | 280 +++++++ .../mutipleSelect/schemaInitializer.test.ts | 0 .../mutipleSelect/schemaSettings.test.ts | 243 ++++++ .../fields/number/schemaInitializer.test.ts | 0 .../fields/number/schemaSettings.test.ts | 298 +++++++ .../oneToMany/schemaInitializer.test.ts | 0 .../fields/oneToMany/schemaSettings.test.ts | 588 +++++++++++++ .../fields/password/schemaInitializer.test.ts | 0 .../fields/password/schemaSettings.test.ts | 280 +++++++ .../fields/percent/schemaInitializer.test.ts | 0 .../fields/percent/schemaSettings.test.ts | 299 +++++++ .../fields/phone/schemaInitializer.test.ts | 0 .../fields/phone/schemaSettings.test.ts | 224 +++++ .../radioGroup/schemaInitializer.test.ts | 0 .../fields/radioGroup/schemaSettings.test.ts | 241 ++++++ .../fields/richText/schemaInitializer.test.ts | 0 .../fields/richText/schemaSettings.test.ts | 281 +++++++ .../fields/sequence/schemaInitializer.test.ts | 0 .../fields/sequence/schemaSettings.test.ts | 79 ++ .../singleLineText/schemaInitializer.test.ts | 0 .../singleLineText/schemaSettings.test.ts | 376 +++++++++ .../singleSelect/schemaInitializer.test.ts | 0 .../singleSelect/schemaSettings.test.ts | 239 ++++++ .../fields/tableOID/schemaInitializer.test.ts | 0 .../fields/tableOID/schemaSettings.test.ts | 136 ++++ .../fields/time/schemaInitializer.test.ts | 21 + .../fields/time/schemaSettings.test.ts | 208 +++++ .../fields/url/schemaInitializer.test.ts | 0 .../__e2e__/fields/url/schemaSettings.test.ts | 212 +++++ .../form-item/commonTesting.ts | 278 ------- .../details-single-data/advanced.test.ts | 51 -- .../details-single-data/basic.test.ts | 81 -- .../details-single-data/choices.test.ts | 65 -- .../details-single-data/datetime.test.ts | 59 -- .../details-single-data/media.test.ts | 124 --- .../details-single-data/relation.test.ts | 256 ------ .../details-single-data/systemInfo.test.ts | 106 --- .../form-item/form-creation/advanced.test.ts | 62 -- .../form-item/form-creation/basic.test.ts | 750 ----------------- .../form-item/form-creation/choices.test.ts | 395 --------- .../form-item/form-creation/datetime.test.ts | 158 ---- .../form-item/form-creation/media.test.ts | 184 ----- .../form-item/form-creation/relation.test.ts | 658 --------------- .../form-creation/systemInfo.test.ts | 81 -- .../form-item/form-edit/advanced.test.ts | 63 -- .../form-item/form-edit/basic.test.ts | 532 ------------ .../form-item/form-edit/choices.test.ts | 289 ------- .../form-item/form-edit/datetime.test.ts | 119 --- .../form-item/form-edit/media.test.ts | 175 ---- .../form-item/form-edit/relation.test.ts | 567 ------------- .../form-item/form-edit/systemInfo.test.ts | 114 --- .../table-column-item/advanced.test.ts | 34 - .../table-column-item/basic.test.ts | 171 ---- .../table-column-item/choices.test.ts | 50 -- .../table-column-item/datetime.test.ts | 34 - .../table-column-item/media.test.ts | 26 - .../table-column-item/relation.test.ts | 105 --- .../table-column-item/systemInfo.test.ts | 50 -- .../table-column-item/utils.ts | 37 - .../src/client/__e2e__/utils.ts | 506 ++++++++++++ 116 files changed, 11712 insertions(+), 5720 deletions(-) create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/calendar.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/connectToDatabaseView.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/expression.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/file.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/general.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/sql.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/tree.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaSettings.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaInitializer.test.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaSettings.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/commonTesting.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/advanced.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/basic.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/choices.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/datetime.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/media.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/relation.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/systemInfo.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/advanced.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/basic.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/choices.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/datetime.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/media.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/relation.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/systemInfo.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/advanced.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/basic.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/choices.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/datetime.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/media.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/relation.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/systemInfo.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/advanced.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/basic.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/choices.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/datetime.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/media.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/relation.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/systemInfo.test.ts delete mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/utils.ts create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/utils.ts diff --git a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx index 007b20c09..b76395cbf 100644 --- a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx @@ -258,8 +258,6 @@ export const AddCollectionAction = (props) => { }); } result.push({ - role: 'button', - 'aria-label': `create-collection-${item.name}`, label: compile(item.title), key: item.name, }); @@ -289,7 +287,7 @@ export const AddCollectionAction = (props) => { {children || ( - )} diff --git a/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx b/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx index 03cd26bc9..bf869e10e 100644 --- a/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx @@ -258,8 +258,6 @@ export const AddFieldAction = (props) => { .filter((child) => ['m2o'].includes(child.name)) .map((child) => { return { - role: 'button', - 'aria-label': `${compile(option.label)}-${child.name}`, label: compile(child.title), title: compile(child.title), key: child.name, @@ -277,8 +275,6 @@ export const AddFieldAction = (props) => { .filter((child) => !['o2o', 'subTable', 'linkTo'].includes(child.name)) .map((child) => { return { - role: 'button', - 'aria-label': `${compile(option.label)}-${child.name}`, label: compile(child.title), title: compile(child.title), key: child.name, @@ -314,7 +310,7 @@ export const AddFieldAction = (props) => { {children || ( - )} diff --git a/packages/core/client/src/collection-manager/Configuration/ConfigurationTabs.tsx b/packages/core/client/src/collection-manager/Configuration/ConfigurationTabs.tsx index f47990b9d..2a0e6dbcc 100644 --- a/packages/core/client/src/collection-manager/Configuration/ConfigurationTabs.tsx +++ b/packages/core/client/src/collection-manager/Configuration/ConfigurationTabs.tsx @@ -191,8 +191,6 @@ export const ConfigurationTabs = () => { return { items: [ { - role: 'button', - 'aria-label': 'edit-category', key: 'edit', label: ( { ), }, { - role: 'button', - 'aria-label': 'delete-category', key: 'delete', label: compile("{{t('Delete category')}}"), onClick: () => remove(item.id), diff --git a/packages/core/test/src/e2e/e2eUtils.ts b/packages/core/test/src/e2e/e2eUtils.ts index d9b507688..50c8bc854 100644 --- a/packages/core/test/src/e2e/e2eUtils.ts +++ b/packages/core/test/src/e2e/e2eUtils.ts @@ -195,8 +195,8 @@ const APP_BASE_URL = process.env.APP_BASE_URL || `http://localhost:${PORT}`; export class NocoPage { private url: string; - private uid: string; - private collectionsName: string[]; + private uid: string | undefined; + private collectionsName: string[] | undefined; private _waitForInit: Promise; constructor( @@ -278,7 +278,7 @@ const _test = base.extend({ await use(mockManualDestroyPage); }, createCollections: async ({ page }, use) => { - let collectionsName = []; + let collectionsName: string[] = []; const _createCollections = async (collectionSettings: CollectionSetting | CollectionSetting[]) => { collectionSettings = omitSomeFields( @@ -295,7 +295,7 @@ const _test = base.extend({ } }, mockCollections: async ({ page }, use) => { - let collectionsName = []; + let collectionsName: string[] = []; const destroy = async () => { if (collectionsName.length) { await deleteCollections(_.uniq(collectionsName)); @@ -312,7 +312,7 @@ const _test = base.extend({ await destroy(); }, mockCollection: async ({ page }, use) => { - let collectionsName = []; + let collectionsName: string[] = []; const destroy = async () => { if (collectionsName.length) { await deleteCollections(_.uniq(collectionsName)); @@ -618,12 +618,12 @@ const generateFakerData = (collectionSetting: CollectionSetting) => { }; const result = {}; - collectionSetting.fields.forEach((field) => { - if (excludeField.includes(field.name)) { + collectionSetting.fields?.forEach((field) => { + if (field.name && excludeField.includes(field.name)) { return; } - if (basicInterfaceToData[field.interface]) { + if (basicInterfaceToData[field.interface] && field.name) { result[field.name] = basicInterfaceToData[field.interface](); } }); @@ -631,30 +631,6 @@ const generateFakerData = (collectionSetting: CollectionSetting) => { return result; }; -/** - * 使用 Faker 为 collection 创建数据 - */ -const createFakerData = async (collectionSettings: CollectionSetting[]) => { - const api = await request.newContext({ - storageState: process.env.PLAYWRIGHT_AUTH_FILE, - }); - - const state = await api.storageState(); - const headers = getHeaders(state); - - for (const item of collectionSettings) { - const data = generateFakerData(item); - const result = await api.post(`/api/${item.name}:create`, { - headers, - form: data, - }); - - if (!result.ok()) { - throw new Error(await result.text()); - } - } -}; - const createRandomData = async (collectionName: string, count = 10, data?: any) => { const api = await request.newContext({ storageState: process.env.PLAYWRIGHT_AUTH_FILE, @@ -714,15 +690,32 @@ function getHeaders(storageState: any) { return headers; } +interface ExpectSettingsMenuParams { + showMenu: () => Promise; + supportedOptions: string[]; + page: Page; + unsupportedOptions?: string[]; +} + /** * 辅助断言 SchemaSettings 的菜单项是否存在 * @param param0 */ -export async function expectSettingsMenu({ showMenu, supportedOptions, page }) { +export async function expectSettingsMenu({ + showMenu, + supportedOptions, + page, + unsupportedOptions, +}: ExpectSettingsMenuParams) { await showMenu(); for (const option of supportedOptions) { await expect(page.getByRole('menuitem', { name: option })).toBeVisible(); } + if (unsupportedOptions) { + for (const option of unsupportedOptions) { + await expect(page.getByRole('menuitem', { name: option })).not.toBeVisible(); + } + } } /** @@ -732,7 +725,8 @@ export async function expectSettingsMenu({ showMenu, supportedOptions, page }) { export async function expectInitializerMenu({ showMenu, supportedOptions, page }) { await showMenu(); for (const option of supportedOptions) { - await expect(page.getByRole('menuitem', { name: option })).toBeVisible(); + // 使用 first 方法避免有重名的导致报错 + await expect(page.getByRole('menuitem', { name: option }).first()).toBeVisible(); } } diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/calendar.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/calendar.test.ts new file mode 100644 index 000000000..5b0450516 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/calendar.test.ts @@ -0,0 +1,80 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Calendar collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('inherits', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Calendar collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Inherits', ['Users']); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('Calendar collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/connectToDatabaseView.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/connectToDatabaseView.test.ts new file mode 100644 index 000000000..75aa786d6 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/connectToDatabaseView.test.ts @@ -0,0 +1,7 @@ +import { test } from '@nocobase/test/e2e'; + +test.describe('create collection', () => {}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/expression.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/expression.test.ts new file mode 100644 index 000000000..293e483dc --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/expression.test.ts @@ -0,0 +1,80 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Expression collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('inherits', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Expression collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Inherits', ['Users']); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('Expression collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/file.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/file.test.ts new file mode 100644 index 000000000..ae08d7a93 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/file.test.ts @@ -0,0 +1,83 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('File collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('File storage', 'Local storage'); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('inherits', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('File collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Inherits', ['Users']); + await collectionSettings.change('File storage', 'Local storage'); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('File collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.change('File storage', 'Local storage'); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/general.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/general.test.ts new file mode 100644 index 000000000..48b4f8ffe --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/general.test.ts @@ -0,0 +1,263 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage, FieldInterface } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('General collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('inherits', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('General collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Inherits', ['Users']); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('General collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); + + test('uncheck more options', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('General collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Generate ID field automatically', false); + await collectionSettings.change('Store the creation user of each record', false); + await collectionSettings.change('Store the last update user of each record', false); + await collectionSettings.change('Store the creation time of each record', false); + await collectionSettings.change('Store the last update time of each record', false); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => { + test('basic', async ({ page, mockCollections }) => { + test.slow(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + const targetCollectionName = `t_${uid()}`; + await mockCollections([ + { + name: targetCollectionName, + }, + { + name: collectionName, + title: collectionDisplayName, + }, + ]); + await collectionManagerPage.goto(); + + const fieldsSettings = await collectionManagerPage.configureFields(collectionName); + // 应该有这些字段显示出来 + await expect(page.getByRole('cell', { name: 'id', exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: 'createdAt', exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: 'createdBy', exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: 'updatedAt', exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: 'updatedBy', exact: true })).toBeVisible(); + + // 添加 table oid 字段 + const tableOIDDisplayName = uid(); + const tableOIDSettings = await fieldsSettings.addField('Table OID'); + await tableOIDSettings.change('Field display name', tableOIDDisplayName); + await tableOIDSettings.submit(); + await expect(page.getByRole('cell', { name: tableOIDDisplayName, exact: true })).toBeVisible(); + + // 添加 basic 类型的字段 + // 注意:有一些必填项之所以缺失,是因为其会被自动填充一个值 + await addField('Single line text'); + await addField('Long text'); + await addField('Phone'); + await addField('Email'); + await addField('URL'); + await addField('Integer'); + await addField('Number'); + await addField('Percent'); + await addField('Password'); + await addField('Color'); + await addField('Icon'); + + // 添加 choices 字段 + await addField('Checkbox'); + await addField('Single select'); + await addField('Multiple select'); + await addField('Radio group'); + await addField('Checkbox group'); + await addField('China region'); + + // 添加 media 字段 + await addField('Markdown'); + await addField('Rich Text'); + await addField('Attachment'); + + // 添加 date & time 字段 + await addField('Datetime'); + await addField('Time'); + + // 添加 relation 字段 + // One to one (belongs to) + const belongsToDisplayName = uid(); + const belongsToSettings = await fieldsSettings.addField('One to one (belongs to)'); + await belongsToSettings.change('Field display name', belongsToDisplayName); + await belongsToSettings.change('Target collection', targetCollectionName); + await belongsToSettings.submit(); + await expect(page.getByRole('cell', { name: belongsToDisplayName, exact: true })).toBeVisible(); + // One to one (has one) + const hasOneDisplayName = uid(); + const hasOneSettings = await fieldsSettings.addField('One to one (has one)'); + await hasOneSettings.change('Field display name', hasOneDisplayName); + await hasOneSettings.change('Target collection', targetCollectionName); + await hasOneSettings.submit(); + await expect(page.getByRole('cell', { name: hasOneDisplayName, exact: true })).toBeVisible(); + // One to many + const oneToManyDisplayName = uid(); + const oneToManySettings = await fieldsSettings.addField('One to many'); + await oneToManySettings.change('Field display name', oneToManyDisplayName); + await oneToManySettings.change('Target collection', targetCollectionName); + await oneToManySettings.submit(); + await expect(page.getByRole('cell', { name: oneToManyDisplayName, exact: true })).toBeVisible(); + // Many to one + const manyToOneDisplayName = uid(); + const manyToOneSettings = await fieldsSettings.addField('Many to one'); + await manyToOneSettings.change('Field display name', manyToOneDisplayName); + await manyToOneSettings.change('Target collection', targetCollectionName); + await manyToOneSettings.submit(); + await expect(page.getByRole('cell', { name: manyToOneDisplayName, exact: true })).toBeVisible(); + // Many to many + const manyToManyDisplayName = uid(); + const manyToManyName = `f_${uid()}`; + const manyToManySettings = await fieldsSettings.addField('Many to many'); + await manyToManySettings.change('Field display name', manyToManyDisplayName); + await manyToManySettings.change('Field name', manyToManyName); + await manyToManySettings.change('Target collection', targetCollectionName); + await manyToManySettings.submit(); + await expect(page.getByRole('cell', { name: manyToManyDisplayName, exact: true })).toBeVisible(); + // 在这里测一下 many to many 字段的编辑和删除,其它字段先不测了 + const newManyToManyDisplayName = uid(); + const manyToManyEditing = await fieldsSettings.edit(manyToManyName, 'Many to many'); + await manyToManyEditing.change('Field display name', newManyToManyDisplayName); + await manyToManyEditing.submit(); + await expect(page.getByRole('cell', { name: newManyToManyDisplayName, exact: true })).toBeVisible(); + await fieldsSettings.deleteItem(manyToManyName); + await expect(page.getByRole('cell', { name: newManyToManyDisplayName, exact: true })).toBeHidden(); + + // 添加 advanced 字段 + // Formula + const formulaDisplayName = uid(); + const formulaSettings = await fieldsSettings.addField('Formula'); + await formulaSettings.change('Field display name', formulaDisplayName); + await formulaSettings.change('Expression', '1+1'); + await formulaSettings.submit(); + await expect(page.getByRole('cell', { name: formulaDisplayName, exact: true })).toBeVisible(); + // Sequence + const sequenceDisplayName = uid(); + const sequenceSettings = await fieldsSettings.addField('Sequence'); + await sequenceSettings.change('Field display name', sequenceDisplayName); + await page.getByRole('button', { name: 'plus Add rule' }).click(); + await sequenceSettings.submit(); + await expect(page.getByRole('cell', { name: sequenceDisplayName, exact: true })).toBeVisible(); + // JSON + await addField('JSON'); + // Collection + await addField('Collection'); + + async function addField(fieldType: FieldInterface) { + const value = uid(); + const fieldSettings = await fieldsSettings.addField(fieldType); + await fieldSettings.change('Field display name', value); + await fieldSettings.submit(); + await expect(page.getByRole('cell', { name: value, exact: true })).toBeVisible(); + } + }); +}); + +test.describe('edit', () => { + test('basic', async ({ page, mockCollection }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + await mockCollection({ + name: collectionName, + title: collectionDisplayName, + }); + await collectionManagerPage.goto(); + + const newCollectionDisplayName = uid(); + const newDescription = uid(); + const newCollectionSettings = await collectionManagerPage.edit(collectionName); + await newCollectionSettings.change('Collection display name', newCollectionDisplayName); + await newCollectionSettings.change('Description', newDescription); + await newCollectionSettings.submit(); + await expect(page.getByRole('cell', { name: newCollectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: newDescription, exact: true })).toBeVisible(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/sql.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/sql.test.ts new file mode 100644 index 000000000..c39b99f6d --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/sql.test.ts @@ -0,0 +1,54 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('SQL collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('SQL', 'SELECT * FROM users;'); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('SQL collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('SQL', 'SELECT * FROM users;'); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/tree.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/tree.test.ts new file mode 100644 index 000000000..7e7220b83 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/collection-template/tree.test.ts @@ -0,0 +1,101 @@ +import { expect, test } from '@nocobase/test/e2e'; +import { uid } from '@nocobase/utils'; +import { CollectionManagerPage } from '../utils'; + +test.describe('create collection', () => { + test('basic', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Tree collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + // Delete -------------------------------------------------------------------------------- + await collectionManagerPage.deleteItem(collectionName); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeHidden(); + }); + + test('inherits', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Tree collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Inherits', ['Users']); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); + + test('categories', async ({ page }) => { + const categoriesName = uid(); + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const description = uid(); + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + await collectionManagerPage.addCategory(categoriesName, 'Red'); + + const collectionSettings = await collectionManagerPage.createCollection('Tree collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Description', description); + await collectionSettings.change('Categories', [categoriesName]); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: collectionName, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: description, exact: true })).toBeVisible(); + await expect(page.getByRole('cell', { name: categoriesName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteCategory(categoriesName); + await collectionManagerPage.deleteItem(collectionName); + }); + + test('uncheck more options', async ({ page }) => { + const collectionDisplayName = uid(); + // 避免以数字开头,会报错 + const collectionName = `t_${uid()}`; + const collectionManagerPage = new CollectionManagerPage(page); + await collectionManagerPage.goto(); + + const collectionSettings = await collectionManagerPage.createCollection('Tree collection'); + await collectionSettings.change('Collection display name', collectionDisplayName); + await collectionSettings.change('Collection name', collectionName); + await collectionSettings.change('Store the creation user of each record', false); + await collectionSettings.change('Store the last update user of each record', false); + await collectionSettings.change('Store the creation time of each record', false); + await collectionSettings.change('Store the last update time of each record', false); + await collectionSettings.submit(); + + await expect(page.getByRole('cell', { name: collectionDisplayName, exact: true })).toBeVisible(); + + await collectionManagerPage.deleteItem(collectionName); + }); +}); + +test.describe('configure fields', () => {}); + +test.describe('edit', () => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaInitializer.test.ts new file mode 100644 index 000000000..2635a4061 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaInitializer.test.ts @@ -0,0 +1,67 @@ +import { expectInitializerMenu, oneTableBlockWithAddNewAndViewAndEditAndMediaFields, test } from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['markdown', 'richtext', 'attachment'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['markdown', 'richtext', 'attachment'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['markdown', 'richtext', 'attachment'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['markdown', 'richtext', 'attachment'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaSettings.test.ts new file mode 100644 index 000000000..c21b0d029 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/attachment/schemaSettings.test.ts @@ -0,0 +1,285 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndMediaFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`, { + exact: true, + }) + .hover(); + }, + expectEditable: async () => { + await expect(page.getByRole('button', { name: 'plus Upload' })).toBeVisible(); + }, + expectReadonly: async () => { + await expect(page.getByRole('button', { name: 'plus Upload' })).not.toBeVisible(); + }, + expectEasyReading: async () => { + await expect(page.getByRole('button', { name: 'plus Upload' })).not.toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'attachment'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first(), + ).toBeVisible(); + }, + expectReadonly: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first() + .hover(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('button', { name: 'delete' }), + ).not.toBeVisible(); + }, + expectEasyReading: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first() + .hover(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('button', { name: 'delete' }), + ).not.toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + // 这里是为了等弹窗中的内容渲染稳定后,再去 hover,防止错位导致测试报错 + await page.waitForTimeout(1000); + await page + .getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Size'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('size', async ({ page, mockPage, mockRecord }) => { + const record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + + // 默认尺寸 + // 这里的尺寸不稳定,所以用 try catch 来处理 + const testDefault = async (value) => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first(), + ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); + }; + try { + await testDefault(94); + } catch (error) { + try { + await testDefault(95); + } catch (err) { + await testDefault(96); + } + } + + // 改为大尺寸 + const testLarge = async (value) => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first(), + ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); + }; + // 这里是为了等弹窗中的内容渲染稳定后,再去 hover,防止错位导致测试报错 + await page.waitForTimeout(1000); + await page + .getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`, { + exact: true, + }) + .hover(); + await page.getByRole('menuitem', { name: 'Size' }).click(); + await page.getByRole('option', { name: 'Large' }).click(); + try { + await testLarge(153); + } catch (err) { + try { + await testLarge(154); + } catch (err) { + await testLarge(152); + } + } + + // 改为小尺寸 + const testSmall = async (value) => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') + .getByRole('link', { name: record.attachment.title }) + .first(), + ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); + }; + await (async (page: Page, fieldName: string) => { + // 这里是为了等弹窗中的内容渲染稳定后,再去 hover,防止错位导致测试报错 + await page.waitForTimeout(1000); + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'attachment'); + await page.getByRole('menuitem', { name: 'Size' }).click(); + await page.getByRole('option', { name: 'Small' }).click(); + try { + await testSmall(25); + } catch (err) { + try { + await testSmall(26); + } catch (err) { + await testSmall(24); + } + } + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'attachment'); + await showSettingsMenu(page, 'attachment'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaInitializer.test.ts new file mode 100644 index 000000000..7a92dab3f --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaInitializer.test.ts @@ -0,0 +1,73 @@ +import { + expectInitializerMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['oneToMany', 'manyToOne', 'manyToMany', 'oneToOneBelongsTo', 'oneToOneHasOne'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['oneToMany', 'manyToOne', 'manyToMany', 'oneToOneBelongsTo', 'oneToOneHasOne'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['oneToMany', 'manyToOne', 'manyToMany', 'oneToOneBelongsTo', 'oneToOneHasOne'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['oneToMany', 'manyToOne', 'manyToMany', 'oneToOneBelongsTo', 'oneToOneHasOne'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts new file mode 100644 index 000000000..da3fdfb43 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts @@ -0,0 +1,548 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo`) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneBelongsTo`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let records; + await testPattern({ + page, + gotoPage: async () => { + records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId(/select-object/) + .click(); + await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo'), + ).toHaveText(`oneToOneBelongsTo:${String(records[0].id)}`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(records[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId('select-object-single') + .click(); + await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); + await expect(page.getByRole('option')).toHaveCount(1); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockRecords, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo`) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneBelongsTo`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let record; + await testPattern({ + page, + gotoPage: async () => { + record = ( + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords) + ).record; + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId(/select-object/), + ).toHaveText(`${record.oneToOneBelongsTo.id}`); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo'), + ).toHaveText(`oneToOneBelongsTo:${record.oneToOneBelongsTo.id}`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const { recordsOfUser } = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') + .getByTestId(/select-object/) + .click(); + await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); + await expect(page.getByRole('option')).toHaveCount(2); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo`) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneBelongsTo`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Field component', + 'Enable link', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); + + test('enable link', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneBelongsTo'); + + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'oneToOneBelongsTo'); + await showSettingsMenu(page, 'oneToOneBelongsTo'); + }, + supportedOptions: [ + 'Custom column title', + 'Column width', + 'Enable link', + 'Title field', + 'Field component', + 'Delete', + ], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaInitializer.test.ts new file mode 100644 index 000000000..0e534358f --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaInitializer.test.ts @@ -0,0 +1,67 @@ +import { expectInitializerMenu, oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, test } from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['checkbox', 'chinaRegion', 'multipleSelect', 'radioGroup', 'singleSelect', 'checkboxGroup'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['checkbox', 'chinaRegion', 'multipleSelect', 'radioGroup', 'singleSelect', 'checkboxGroup'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['checkbox', 'chinaRegion', 'multipleSelect', 'radioGroup', 'singleSelect', 'checkboxGroup'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['checkbox', 'chinaRegion', 'multipleSelect', 'radioGroup', 'singleSelect', 'checkboxGroup'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaSettings.test.ts new file mode 100644 index 000000000..9d78cd0f4 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkbox/schemaSettings.test.ts @@ -0,0 +1,241 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.checkbox-checkbox`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkbox`, { + exact: true, + }) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkbox'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + // 默认应该是没有被选中的,点击后应该被选中 + await page.getByLabel('block-item-VariableInput-').getByRole('checkbox').click(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).toBeChecked(); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkbox'), + expectEditable: async () => { + // 默认是未选中的状态,所以先选中 + await page + .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') + .getByRole('checkbox') + .click(); + }, + expectReadonly: async () => { + // checkbox 应该被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // checkbox 应该被隐藏,然后只显示一个图标 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).not.toBeVisible(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') + .getByRole('img', { name: 'check' }), + ).toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.checkbox-checkbox`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkbox`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkbox'), + expectEditable: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).toBeChecked({ checked: record.checkbox }); + }, + expectReadonly: async () => { + // checkbox 应该被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // checkbox 应该被隐藏,然后只显示一个图标 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), + ).not.toBeVisible(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') + .getByRole('img', { name: 'check' }), + ).toBeVisible({ visible: record.checkbox }); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.checkbox-checkbox`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkbox`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'checkbox'); + await showSettingsMenu(page, 'checkbox'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaSettings.test.ts new file mode 100644 index 000000000..4e6be001e --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/checkboxGroup/schemaSettings.test.ts @@ -0,0 +1,248 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkboxGroup`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkboxGroup'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByLabel('Option1').click(); + }, + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }), + ).toBeChecked(); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkboxGroup'), + expectEditable: async () => { + // 默认是未选中的状态,所以先选中 + await page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }) + .click(); + }, + expectReadonly: async () => { + // checkbox 应该被禁用 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // checkbox 应该被隐藏,然后只显示一个标签 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }), + ).not.toBeVisible(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByText('Option1'), + ).toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkboxGroup`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'checkboxGroup'), + expectEditable: async () => { + for (const option of record.checkboxGroup) { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: option }), + ).toBeChecked(); + } + }, + expectReadonly: async () => { + // checkbox 应该被禁用 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // checkbox 应该被隐藏,然后只显示标签 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') + .getByRole('checkbox', { name: 'Option1' }), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup'), + ).toHaveText(`checkboxGroup:${record.checkboxGroup.join('')}`, { ignoreCase: true }); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.checkboxGroup`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'checkboxGroup'); + await showSettingsMenu(page, 'checkboxGroup'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaSettings.test.ts new file mode 100644 index 000000000..d8714d745 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/chinaRegion/schemaSettings.test.ts @@ -0,0 +1,249 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.chinaRegion-chinaRegion`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.chinaRegion`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'chinaRegion'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').click(); + await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); + await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); + await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), + ).toHaveText('chinaRegion:北京市/市辖区/东城区'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'chinaRegion'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .click(); + await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); + await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); + await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .getByRole('combobox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .getByRole('combobox'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), + ).toHaveText('chinaRegion:北京市 / 市辖区 / 东城区'); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.chinaRegion-chinaRegion`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.chinaRegion`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'chinaRegion'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .click(); + await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); + await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); + await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .getByRole('combobox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') + .locator('.ant-select') + .getByRole('combobox'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), + ).toHaveText('chinaRegion:北京市 / 市辖区 / 东城区'); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.chinaRegion-chinaRegion`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.chinaRegion`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'chinaRegion'); + await showSettingsMenu(page, 'chinaRegion'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaInitializer.test.ts new file mode 100644 index 000000000..a8f460d07 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaInitializer.test.ts @@ -0,0 +1,71 @@ +import { + expectInitializerMenu, + oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, + test, +} from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['formula', 'sequence', 'JSON', 'collection'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['formula', 'sequence', 'JSON', 'collection'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['formula', 'sequence', 'JSON', 'collection'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['formula', 'sequence', 'JSON', 'collection'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaSettings.test.ts new file mode 100644 index 000000000..bc1c762e8 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/collection/schemaSettings.test.ts @@ -0,0 +1,91 @@ +import { expectSettingsMenu, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.collection-collection`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.collection`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Delete', + ], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.collection-collection`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.collection`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.collection-collection`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.collection`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'collection'); + await showSettingsMenu(page, 'collection'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); + +test.describe('table column & table & record picker', () => { + test('supported options', async ({ page }) => {}); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaInitializer.test.ts new file mode 100644 index 000000000..dd82910d1 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaInitializer.test.ts @@ -0,0 +1,115 @@ +import { expectInitializerMenu, oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test } from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: [ + 'color', + 'email', + 'icon', + 'singleLineText', + 'integer', + 'number', + 'password', + 'percent', + 'phone', + 'longText', + 'url', + ], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: [ + 'color', + 'email', + 'icon', + 'singleLineText', + 'integer', + 'number', + 'password', + 'percent', + 'phone', + 'longText', + 'url', + ], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: [ + 'color', + 'email', + 'icon', + 'singleLineText', + 'integer', + 'number', + 'password', + 'percent', + 'phone', + 'longText', + 'url', + ], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: [ + 'color', + 'email', + 'icon', + 'singleLineText', + 'integer', + 'number', + 'password', + 'percent', + 'phone', + 'longText', + 'url', + ], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaSettings.test.ts new file mode 100644 index 000000000..3717ea6aa --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/color/schemaSettings.test.ts @@ -0,0 +1,239 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { + clickDeleteAndOk, + createColumnItem, + showSettingsMenu, + testDisplayTitle, + testEditDescription, + testEditFieldTitle, + testPattern, + testRequired, +} from '../../utils'; + +test.describe('form item & create form', () => { + test('set default value', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + // 简单测试下是否有选项,值的话无法选中,暂时测不了 + await expect(page.getByRole('menuitem', { name: 'Set default value' })).toBeVisible(); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`) + .hover(); + }, + expectEditable: async () => { + // 默认情况下显示颜色选择框 + await page.getByLabel('color-picker-normal').hover(); + await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).toBeVisible(); + }, + expectReadonly: async () => { + // 只读模式下,不会显示颜色弹窗 + await page.getByLabel('color-picker-normal').hover(); + await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).not.toBeVisible(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('color-picker-read-pretty')).toBeVisible(); + }, + }); + }); + + test('edit field title', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await testEditFieldTitle(page); + }); + + test('display title', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await testDisplayTitle(page, 'color'); + }); + + test('delete', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await clickDeleteAndOk(page); + await expect(page.getByText(`color:`)).not.toBeVisible(); + }); + + test('edit description', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await testEditDescription(page); + }); + + test('required', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await testRequired(page); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'color'), + expectEditable: async () => { + // 默认情况下显示颜色选择框 + await page.getByLabel('color-picker-normal').hover(); + await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).toBeVisible(); + }, + expectReadonly: async () => { + // 只读模式下,不会显示颜色弹窗 + await page.getByLabel('color-picker-normal').hover(); + await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).not.toBeVisible(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('color-picker-read-pretty')).toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('edit field title', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + await testEditFieldTitle(page); + }); + + test('display title', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + await testDisplayTitle(page, 'color'); + }); + + test('delete', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + await clickDeleteAndOk(page); + await expect(page.getByText(`color:`)).not.toBeVisible(); + }); + + test('edit tooltip', async ({ page, mockPage, mockRecord, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.color-color`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.color`).hover(); + + await page.getByRole('menuitem', { name: 'Edit tooltip' }).click(); + await page.getByRole('dialog').getByRole('textbox').click(); + await page.getByRole('dialog').getByRole('textbox').fill('testing edit tooltip'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await page.getByRole('img', { name: 'question-circle' }).hover(); + await expect(page.getByText('testing edit tooltip')).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'color'); + await showSettingsMenu(page, 'color'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaInitializer.test.ts new file mode 100644 index 000000000..60dc80d84 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaInitializer.test.ts @@ -0,0 +1,71 @@ +import { + expectInitializerMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['Created at', 'Last updated at', 'Created by', 'Last updated by', 'ID', 'Table OID'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['Created at', 'Last updated at', 'Created by', 'Last updated by', 'ID', 'Table OID'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['Created at', 'Last updated at', 'Created by', 'Last updated by', 'ID', 'Table OID'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['Created at', 'Last updated at', 'Created by', 'Last updated by', 'ID', 'Table OID'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaSettings.test.ts new file mode 100644 index 000000000..1cd598d64 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdAt/schemaSettings.test.ts @@ -0,0 +1,152 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdAt`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Pattern', + 'Date display format', + 'Delete', + ], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdAt`) + .hover(); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdAt`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Pattern', + 'Date display format', + 'Delete', + ], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'createdAt'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdAt`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Date display format'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'createdAt'); + await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'Created at'); + await showSettingsMenu(page, 'Created at'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaSettings.test.ts new file mode 100644 index 000000000..5051d3650 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/createdBy/schemaSettings.test.ts @@ -0,0 +1,138 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Enable link', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdBy`) + .hover(); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Enable link', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'createdBy'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.createdBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.createdBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Enable link'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'createdBy'); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'Created by'); + await showSettingsMenu(page, 'Created by'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Enable link', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaInitializer.test.ts new file mode 100644 index 000000000..0f982e116 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaInitializer.test.ts @@ -0,0 +1,71 @@ +import { + expectInitializerMenu, + oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, + test, +} from '@nocobase/test/e2e'; + +test.describe('form item & create form', () => { + test('configure fields', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['datetime', 'time'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover(); + }, + supportedOptions: ['datetime', 'time'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('configure fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover(); + }, + supportedOptions: ['datetime', 'time'], + }); + }); +}); + +test.describe('table column & table', () => { + test('configure columns', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectInitializerMenu({ + page, + showMenu: async () => { + await page.getByLabel('schema-initializer-TableV2-').hover(); + }, + supportedOptions: ['datetime', 'time'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaSettings.test.ts new file mode 100644 index 000000000..3657e74c9 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/datetime/schemaSettings.test.ts @@ -0,0 +1,327 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, + test, +} from '@nocobase/test/e2e'; +import dayjs from 'dayjs'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.datetime-datetime`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.datetime`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Date display format', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByPlaceholder('Select date').click(); + await page.getByText('Today').click(); + }, + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toHaveValue(dayjs().format('YYYY-MM-DD')); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date') + .click(); + await page.getByText('Today').click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( + `datetime:${dayjs().format('YYYY-MM-DD')}`, + ); + }, + }); + }); + + test('date display format', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + })(mockPage); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'); + await page.getByRole('menuitem', { name: 'Date display format' }).click(); + await page.getByLabel('YYYY/MM/DD').click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 输入一个值,然后验证格式是否正确 + await page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date') + .click(); + await page.getByText('Today').click(); + + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toHaveValue(dayjs().format('YYYY/MM/DD')); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.datetime-datetime`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.datetime`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Pattern', + 'Date display format', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toHaveValue(dayjs(record.datetime).format('YYYY-MM-DD')); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( + `datetime:${dayjs(record.datetime).format('YYYY-MM-DD')}`, + ); + }, + }); + }); + + test('date display format', async ({ page, mockPage, mockRecord }) => { + const record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'); + await page.getByRole('menuitem', { name: 'Date display format' }).click(); + await page.getByLabel('YYYY/MM/DD').click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') + .getByPlaceholder('Select date'), + ).toHaveValue(dayjs(record.datetime).format('YYYY/MM/DD')); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.datetime-datetime`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.datetime`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Date display format'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('date display format', async ({ page, mockPage, mockRecord }) => { + const record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'datetime'); + await page.getByRole('menuitem', { name: 'Date display format' }).click(); + await page.getByLabel('YYYY/MM/DD').click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( + `datetime:${dayjs(record.datetime).format('YYYY/MM/DD')}`, + ); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'datetime'); + await showSettingsMenu(page, 'datetime'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], + }); + }); + + test('date display format', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + const records = await mockRecords('general', 1); + await nocoPage.goto(); + + await createColumnItem(page, 'datetime'); + await showSettingsMenu(page, 'datetime'); + await page.getByRole('menuitem', { name: 'Date display format' }).click(); + await page.getByLabel('MM/DD/YY').click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await expect( + page.getByRole('cell', { name: dayjs(records[0].datetime).format('MM/DD/YY'), exact: true }), + ).toBeVisible(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaSettings.test.ts new file mode 100644 index 000000000..09720079a --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/email/schemaSettings.test.ts @@ -0,0 +1,223 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.email-email`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.email`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'email'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'test@nocobase.com', + variableValue: ['Current user', 'Email'], + expectConstantValue: () => + expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).toHaveValue('test@nocobase.com'), + expectVariableValue: () => + expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).toHaveValue('admin@nocobase.com'), + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'email'), + expectEditable: async () => { + // 填充一个值,方便后面断言 + await page + .getByLabel('block-item-CollectionField-general-form-general.email-email') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.email-email') + .getByRole('textbox') + .fill('admin@nocobase.com'); + }, + expectReadonly: async () => { + // 输入框应该被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框应该消失,直接显示值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.email-email')).toHaveText( + 'email:admin@nocobase.com', + ); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.email-email`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.email`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'email'), + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).toHaveValue(record.email); + }, + expectReadonly: async () => { + // 输入框应该被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框应该消失,直接显示值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.email-email')).toHaveText( + `email:${record.email}`, + ); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.email-email`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.email`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'email'); + await showSettingsMenu(page, 'email'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaSettings.test.ts new file mode 100644 index 000000000..45c6d24ea --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/formula/schemaSettings.test.ts @@ -0,0 +1,79 @@ +import { expectSettingsMenu, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.formula-formula`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.formula`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.formula-formula`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.formula`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.formula-formula`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.formula`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'formula'); + await showSettingsMenu(page, 'formula'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts new file mode 100644 index 000000000..d04b56845 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts @@ -0,0 +1,543 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneHasOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let records; + await testPattern({ + page, + gotoPage: async () => { + records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId(/select-object/) + .click(); + + // 目前的情况下,在 one to one (has one) 的字段中,只有 ID 为 1 的数据可以被选中,mock 的数据无法被选中 + await page.getByRole('option', { name: '1', exact: true }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne'), + ).toHaveText(`oneToOneHasOne:1`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(records[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId('select-object-single') + .click(); + // 默认只显示 id 为 1 的数据,因为设置了只过滤 id 为 3 的数据,所以这里的下拉列表应该为空 + await expect(page.getByRole('option')).toHaveCount(0); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockRecords, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneHasOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let record; + await testPattern({ + page, + gotoPage: async () => { + record = ( + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords) + ).record; + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId(/select-object/), + ).toHaveText(`${record.oneToOneHasOne.id}`); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne'), + ).toHaveText(`oneToOneHasOne:${record.oneToOneHasOne.id}`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill('1'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue('1'); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') + .getByTestId(/select-object/) + .click(); + await expect(page.getByRole('option')).toHaveCount(2); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneHasOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Field component', + 'Enable link', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); + + test('enable link', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToOneHasOne'); + + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'oneToOneHasOne'); + await showSettingsMenu(page, 'oneToOneHasOne'); + }, + supportedOptions: [ + 'Custom column title', + 'Column width', + 'Enable link', + 'Title field', + 'Field component', + 'Delete', + ], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaSettings.test.ts new file mode 100644 index 000000000..0249e9ee6 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/icon/schemaSettings.test.ts @@ -0,0 +1,201 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.icon-icon`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.icon`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'icon'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByRole('button', { name: 'Select icon' }).click(); + await page.getByLabel('account-book').locator('svg').click(); + }, + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.icon-icon') + .getByRole('button', { name: 'account-book' }), + ).toBeVisible(); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'icon'), + expectEditable: async () => { + // 默认情况下可以编辑图标 + await page.getByRole('button', { name: 'Select icon' }).click(); + await page.getByLabel('account-book').locator('svg').click(); + }, + expectReadonly: async () => { + // 只读模式下,选择图标按钮会被禁用 + await expect(page.getByRole('button', { name: 'account-book' })).toBeDisabled(); + }, + expectEasyReading: async () => { + // 按钮会消失,只剩下图标 + await expect(page.getByRole('button', { name: 'account-book' })).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.icon-icon').getByLabel('account-book'), + ).toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.icon-icon`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.icon`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + record = await mockRecord('general'); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.icon-icon`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.icon`) + .hover(); + }, + expectEditable: async () => { + // 默认情况下可以编辑图标 + await page.getByRole('button', { name: 'Select icon' }).click(); + await page.getByLabel('account-book').locator('svg').click(); + }, + expectReadonly: async () => { + await expect(page.getByRole('button', { name: 'account-book' })).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect(page.getByRole('button', { name: 'account-book' })).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.icon-icon').getByLabel('account-book'), + ).toBeVisible(); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.icon-icon`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.icon`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'icon'); + await showSettingsMenu(page, 'icon'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaSettings.test.ts new file mode 100644 index 000000000..8261228fe --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/id/schemaSettings.test.ts @@ -0,0 +1,108 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.id-`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.id`).hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.id-`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.id`).hover(); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.id-`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.id`).hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'id'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.id-`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.id`).hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'ID'); + await showSettingsMenu(page, 'ID'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaSettings.test.ts new file mode 100644 index 000000000..340141b4c --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/integer/schemaSettings.test.ts @@ -0,0 +1,284 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.integer-integer`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.integer`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'integer'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + variableValue: ['Current user', 'ID'], // 值为 1 + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('112233'); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).toHaveValue('112233'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).toHaveValue('1'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'integer'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.integer-integer') + .getByRole('spinbutton') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.integer-integer') + .getByRole('spinbutton') + .fill('112233'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText( + 'integer:112233', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'integer'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.integer-integer`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.integer`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'integer'), + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).toHaveValue(String(record.integer)); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText( + `integer:${record.integer}`, + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'integer'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.integer-integer`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.integer`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'integer'); + await showSettingsMenu(page, 'integer'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaSettings.test.ts new file mode 100644 index 000000000..8f6d2d9f6 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/json/schemaSettings.test.ts @@ -0,0 +1,87 @@ +import { expectSettingsMenu, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.JSON-JSON`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.JSON`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Delete', + ], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.JSON-JSON`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.JSON`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.JSON-JSON`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.JSON`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'JSON'); + await showSettingsMenu(page, 'JSON'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaSettings.test.ts new file mode 100644 index 000000000..15a97a8ae --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedAt/schemaSettings.test.ts @@ -0,0 +1,93 @@ +import { expectSettingsMenu, oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, test } from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedAt`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Pattern', + 'Date display format', + 'Delete', + ], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedAt`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Pattern', + 'Date display format', + 'Delete', + ], + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedAt-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedAt`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Date display format'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'Last updated at'); + await showSettingsMenu(page, 'Last updated at'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaSettings.test.ts new file mode 100644 index 000000000..c6233df45 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/lastUpdatedBy/schemaSettings.test.ts @@ -0,0 +1,138 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Enable link', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedBy`) + .hover(); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Enable link', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'updatedBy'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.updatedBy-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.updatedBy`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip', 'Enable link'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'updatedBy'); + await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'Last updated by'); + await showSettingsMenu(page, 'Last updated by'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Enable link', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaSettings.test.ts new file mode 100644 index 000000000..76af85435 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/longText/schemaSettings.test.ts @@ -0,0 +1,286 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.longText-longText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.longText`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: async () => { + await page.getByLabel('drawer-Action.Container-general-Add record-mask').click(); + }, + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'longText'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'test long text', + variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).toHaveValue('test long text'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).toHaveValue('admin@nocobase.com'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'longText'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.longText-longText') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.longText-longText') + .getByRole('textbox') + .fill('test long text'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.longText-longText')).toHaveText( + 'longText:test long text', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'longText'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.longText-longText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.longText`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + record = await mockRecord('general'); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.longText-longText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.longText`) + .hover(); + }, + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).toHaveValue(record.longText); + + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.longText-longText') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.longText-longText') + .getByRole('textbox') + .fill('test long text'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.longText-longText')).toHaveText( + `longText:test long text`, + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'longText'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.longText-longText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.longText`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'longText'); + await showSettingsMenu(page, 'longText'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts new file mode 100644 index 000000000..227cf87f2 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts @@ -0,0 +1,769 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToMany-manyToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Allow multiple', + 'Pattern', + 'Title field', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecords }) => { + let recordsOfUser; + await testDefaultValue({ + page, + gotoPage: async () => { + recordsOfUser = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByTestId('select-object-multiple').click(); + await page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true }).click(); + await page.getByRole('option', { name: String(recordsOfUser[1].id), exact: true }).click(); + await page.getByRole('option', { name: String(recordsOfUser[2].id), exact: true }).click(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), + ).toHaveText(`manyToMany:${recordsOfUser.map((record) => record.id).join('')}`); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let records; + await testPattern({ + page, + gotoPage: async () => { + records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple') + .click(); + await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); + await page.getByRole('option', { name: String(records[1].id), exact: true }).click(); + await page.getByRole('option', { name: String(records[2].id), exact: true }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple'), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), + ).toHaveText(`manyToMany:${records.map((record) => record.id).join(',')}`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(records[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple') + .click(); + await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); + await expect(page.getByRole('option')).toHaveCount(1); + }); + + test('set default sorting rules', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); + + // 配置 + await page.getByRole('button', { name: 'Add sort field' }).click(); + await page.getByTestId('select-single').click(); + await page.getByRole('option', { name: 'ID', exact: true }).click(); + await page.getByText('DESC', { exact: true }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); + await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID'); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + + // 选择 Record picker + await page.getByRole('option', { name: 'Record picker', exact: true }).click(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-data-picker'), + ).toBeVisible(); + + // 选择 Sub-table + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + await page.getByRole('option', { name: 'Sub-table', exact: true }).click(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByLabel('schema-initializer-AssociationField.SubTable-TableColumnInitializers-users'), + ).toBeVisible(); + + // 选择 Sub-form + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + await page.getByRole('option', { name: 'Sub-form', exact: true }).click(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByLabel('schema-initializer-Grid-FormItemInitializers-users'), + ).toBeVisible(); + + // 选择 Sub-form(Popover) + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + await page.getByRole('option', { name: 'Sub-form(Popover)', exact: true }).click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByRole('img', { name: 'edit' }) + .click(); + await expect(page.getByTestId('popover-CollectionField-general')).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('allow multiple', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockRecords, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToMany-manyToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Allow multiple', + 'Pattern', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let record; + await testPattern({ + page, + gotoPage: async () => { + record = ( + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords) + ).record; + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple'), + ).toHaveText(`${record.manyToMany.map((item) => item.id).join('')}`); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple'), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), + ).toHaveText(`manyToMany:${record.manyToMany.map((item) => item.id).join(',')}`); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const { recordsOfUser } = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .getByTestId('select-object-multiple') + .click(); + await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); + }); + + test('set default sorting rules', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); + + // 配置 + await page.getByRole('button', { name: 'Add sort field' }).click(); + await page.getByTestId('select-single').click(); + await page.getByRole('option', { name: 'ID', exact: true }).click(); + await page.getByText('DESC', { exact: true }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); + await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID'); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('allow multiple', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToMany-manyToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Field component', + 'Enable link', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); + + test('enable link', async ({ page, mockPage, mockRecords }) => { + // test.fail(); + const record = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + + // 初始状态是一个可点击的链接 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .locator('a') + .filter({ hasText: record.manyToMany[0].id }), + ).toBeVisible(); + + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToMany'); + + // 默认情况下是开启状态 + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + await page.getByRole('menuitem', { name: 'Enable link' }).click(); + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked(); + + // 应变为非链接状态 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .locator('a') + .filter({ hasText: record.manyToMany[0].id }), + ).not.toBeVisible(); + + // 再次开启链接状态 + await page.getByRole('menuitem', { name: 'Enable link' }).click(); + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') + .locator('a') + .filter({ hasText: record.manyToMany[0].id }), + ).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'manyToMany'); + await showSettingsMenu(page, 'manyToMany'); + }, + supportedOptions: [ + 'Custom column title', + 'Column width', + 'Enable link', + 'Title field', + 'Field component', + 'Delete', + ], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts new file mode 100644 index 000000000..97f6e6f3b --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts @@ -0,0 +1,639 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToOne-manyToOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecords }) => { + let records; + await testDefaultValue({ + page, + gotoPage: async () => { + records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page + .getByLabel('block-item-VariableInput-') + .getByTestId(/select-object/) + .click(); + await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); + await page + .getByLabel('block-item-VariableInput-') + .getByTestId(/select-object/) + .click(); + await page.getByRole('option', { name: String(records[1].id), exact: true }).click(); + await page + .getByLabel('block-item-VariableInput-') + .getByTestId(/select-object/) + .click(); + await page.getByRole('option', { name: String(records[2].id), exact: true }).click(); + }, + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/), + ).toHaveText(String(records[2].id)); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let records; + await testPattern({ + page, + gotoPage: async () => { + records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/) + .click(); + await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne')).toHaveText( + `manyToOne:${String(records[0].id)}`, + ); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(records[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId('select-object-single') + .click(); + await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); + await expect(page.getByRole('option')).toHaveCount(1); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockRecords, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToOne-manyToOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Pattern', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let record; + await testPattern({ + page, + gotoPage: async () => { + record = ( + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords) + ).record; + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/), + ).toHaveText(`${record.manyToOne.id}`); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne')).toHaveText( + `manyToOne:${record.manyToOne.id}`, + ); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const { recordsOfUser } = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') + .getByTestId(/select-object/) + .click(); + await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); + await expect(page.getByRole('option')).toHaveCount(2); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.manyToOne-manyToOne`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToOne`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Field component', + 'Enable link', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); + + test('enable link', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'manyToOne'); + + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'manyToOne'); + await showSettingsMenu(page, 'manyToOne'); + }, + supportedOptions: [ + 'Custom column title', + 'Column width', + 'Enable link', + 'Title field', + 'Field component', + 'Delete', + ], + }); + }); + + test('enable link', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'manyToOne'); + await showSettingsMenu(page, 'manyToOne'); + + // 默认开启 enable link + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeVisible(); + + // 关闭 enable link + await page.getByRole('menuitem', { name: 'Enable link' }).click(); + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked(); + await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeHidden(); + + // 再次开启 + await page.getByRole('menuitem', { name: 'Enable link' }).click(); + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'manyToOne'); + await showSettingsMenu(page, 'manyToOne'); + + // 默认是 ID + await expect(page.getByRole('menuitem', { name: 'Title field' })).toHaveText('Title fieldID'); + await expect(page.getByRole('cell', { name: record.manyToOne.id, exact: true })).toBeVisible(); + + // 修改为 nickname + await page.getByRole('menuitem', { name: 'Title field' }).click(); + await page.getByRole('option', { name: 'Nickname' }).click(); + await page.mouse.move(300, 0); + await expect(page.getByRole('cell', { name: record.manyToOne.nickname, exact: true })).toBeVisible(); + }); + + test('field component', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'manyToOne'); + await showSettingsMenu(page, 'manyToOne'); + + // 默认是 Title + await expect(page.getByRole('menuitem', { name: 'Field component' })).toHaveText('Field componentTitle'); + + // 修改为 Tag + await page.getByRole('menuitem', { name: 'Field component' }).click(); + await page.getByRole('option', { name: 'Tag' }).click(); + // 修改成功之后会显示 Tag color field 选项 + await expect(page.getByRole('menuitem', { name: 'Tag color field' })).toBeVisible(); + await expect( + page.getByRole('cell', { name: record.manyToOne.id, exact: true }).filter({ has: page.locator('.ant-tag') }), + ).toBeVisible(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaSettings.test.ts new file mode 100644 index 000000000..b5ef147ad --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/markdown/schemaSettings.test.ts @@ -0,0 +1,280 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndMediaFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Delete', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord }) => { + await testDefaultValue({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, { + exact: true, + }) + .hover(); + }, + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'test markdown', + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).toHaveValue('test markdown'); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, { + exact: true, + }) + .hover(); + }, + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.markdown-markdown') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.markdown-markdown') + .getByRole('textbox') + .fill('test markdown pattern'); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown')).toHaveText( + `markdown:test markdown pattern`, + ); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, { + exact: true, + }) + .hover(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, { + exact: true, + }) + .hover(); + + await expectSettingsMenu({ + page, + showMenu: async () => {}, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'markdown'), + expectEditable: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).toHaveValue(record.markdown); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown')).toHaveText( + `markdown:${record.markdown}`, + ); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'markdown'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'markdown'); + await showSettingsMenu(page, 'markdown'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaSettings.test.ts new file mode 100644 index 000000000..009d77683 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/mutipleSelect/schemaSettings.test.ts @@ -0,0 +1,243 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.multipleSelect-multipleSelect`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.multipleSelect`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'multipleSelect'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByTestId('select-multiple').click(); + await page.getByRole('option', { name: 'Option1' }).click(); + await page.getByRole('option', { name: 'Option2' }).click(); + await page.getByRole('option', { name: 'Option3' }).click(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), + ).toHaveText('multipleSelect:Option1Option2Option3'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'multipleSelect'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple') + .click(); + await page.getByRole('option', { name: 'Option1' }).click(); + await page.getByRole('option', { name: 'Option2' }).click(); + await page.getByRole('option', { name: 'Option3' }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple'), + ).toHaveClass(/ant-select-disabled/); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), + ).toHaveText('multipleSelect:Option1Option2Option3'); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.multipleSelect-multipleSelect`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.multipleSelect`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'multipleSelect'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple'), + ).toHaveText(`${record.multipleSelect.join('')}`, { ignoreCase: true }); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple'), + ).toHaveClass(/ant-select-disabled/); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') + .getByTestId('select-multiple'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), + ).toHaveText(`multipleSelect:${record.multipleSelect.join('')}`, { ignoreCase: true }); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.multipleSelect-multipleSelect`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.multipleSelect`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'multipleSelect'); + await showSettingsMenu(page, 'multipleSelect'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaSettings.test.ts new file mode 100644 index 000000000..0f6f79b92 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/number/schemaSettings.test.ts @@ -0,0 +1,298 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.number-number`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.number`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'number'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('11.22'); + }, + variableValue: ['Current user', 'ID'], // 值为 1 + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).toHaveValue('11.22'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).toHaveValue('1'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + // TODO: number 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数不应该被去掉; + test.fail(); + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'number'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.number-number') + .getByRole('spinbutton') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.number-number') + .getByRole('spinbutton') + .fill('11.22'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.number-number')).toHaveText( + 'number:11.22', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'number'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.number-number`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.number`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + // TODO: number 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数不应该被去掉; + test.fail(); + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'number'), + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).toHaveValue(String(record.number)); + + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.number-number') + .getByRole('spinbutton') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.number-number') + .getByRole('spinbutton') + .fill('11.22'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.number-number')).toHaveText( + 'number:11.22', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'number'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.number-number`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.number`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'number'); + await showSettingsMenu(page, 'number'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts new file mode 100644 index 000000000..a3c8c199c --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts @@ -0,0 +1,588 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToMany-oneToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Allow multiple', + 'Pattern', + 'Title field', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + await testPattern({ + page, + gotoPage: async () => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + }, + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple') + .click(); + // 目前的情况下,在 one to many 的字段中,只有 ID 为 1 的数据可以被选中 + await page.getByRole('option', { name: '1', exact: true }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple'), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany')).toHaveText( + `oneToMany:1`, + ); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const records = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill(String(records[0].id)); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple') + .click(); + // 默认只显示 id 为 1 的数据,因为设置了只过滤 id 为 3 的数据,所以这里的下拉列表应该为空,mock 的数据无法被选中 + await expect(page.getByRole('option')).toHaveCount(0); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('allow multiple', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + await nocoPage.goto(); + + return recordsOfUser; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockRecords, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('users', 3); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToMany-oneToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set the data scope', + 'Set default sorting rules', + 'Field component', + 'Quick create', + 'Allow multiple', + 'Pattern', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecords }) => { + let record; + await testPattern({ + page, + gotoPage: async () => { + record = ( + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords) + ).record; + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple'), + ).toHaveText(`${record.oneToMany.map((item) => item.id).join('')}`); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple'), + ).toHaveClass(/ant-select-disabled/); + // 在这里等待一下,防止因闪烁导致下面的断言失败 + await page.waitForTimeout(100); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany')).toHaveText( + `oneToMany:${record.oneToMany.map((item) => item.id).join(',')}`, + ); + }, + }); + }); + + test('Set the data scope', async ({ page, mockPage, mockRecords }) => { + const { record } = await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await page.getByText('Add condition', { exact: true }).click(); + await page.getByTestId('select-filter-field').click(); + await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill('1'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 再次打开弹窗,设置的值应该还在 + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); + await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); + await expect(page.getByRole('spinbutton')).toHaveValue('1'); + await page.getByRole('button', { name: 'Cancel', exact: true }).click(); + + // 数据应该被过滤了 + await page + .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') + .getByTestId('select-object-multiple') + .click(); + // 但是在编辑模式下,本身已经有数据,所以需要加上已有数据的个数 + await expect(page.getByRole('option')).toHaveCount(1 + record.oneToMany.length); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); + }); + + test('quick create', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + + await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); + }); + + test('allow multiple', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const recordsOfUser = await mockRecords('users', 3); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return { record, recordsOfUser }; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecords('general', 1); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.oneToMany-oneToMany`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToMany`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit tooltip', + 'Field component', + 'Enable link', + 'Title field', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('field component', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await page.getByRole('menuitem', { name: 'Field component' }).click(); + + // 断言支持的选项 + await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); + await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); + }); + + test('title field', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); + }); + + test('enable link', async ({ page, mockPage, mockRecords }) => { + await (async (mockPage, mockRecords) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + const record = (await mockRecords('general', 1))[0]; + await nocoPage.goto(); + + return record; + })(mockPage, mockRecords); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'oneToMany'); + + await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'oneToMany'); + await showSettingsMenu(page, 'oneToMany'); + }, + supportedOptions: [ + 'Custom column title', + 'Column width', + 'Enable link', + 'Title field', + 'Field component', + 'Delete', + ], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaSettings.test.ts new file mode 100644 index 000000000..e10604a66 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/password/schemaSettings.test.ts @@ -0,0 +1,280 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.password-password`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.password`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'password'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'test112233password', + variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).toHaveValue('test112233password'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).toHaveValue('admin@nocobase.com'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'password'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.password-password') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.password-password') + .getByRole('textbox') + .fill('test112233password'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.password-password')).toHaveText( + 'password:********', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'password'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.password-password`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.password`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + record = await mockRecord('general'); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.password-password`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.password`) + .hover(); + }, + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.password-password') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.password-password') + .getByRole('textbox') + .fill('test112233password'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.password-password')).toHaveText( + 'password:********', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'password'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.password-password`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.password`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'password'); + await showSettingsMenu(page, 'password'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaSettings.test.ts new file mode 100644 index 000000000..39085b214 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/percent/schemaSettings.test.ts @@ -0,0 +1,299 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.percent-percent`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.percent`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'percent'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); + await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('11.22'); + }, + variableValue: ['Current user', 'ID'], // 值为 1 + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).toHaveValue('11.22'); + }, + expectVariableValue: async () => { + // 数字 1 转换为百分比后为 100% + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).toHaveValue('100'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + // TODO: percent 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数点不应该被去掉; + test.fail(); + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'percent'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.percent-percent') + .getByRole('spinbutton') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.percent-percent') + .getByRole('spinbutton') + .fill('11.22'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.percent-percent')).toHaveText( + 'percent:11.22%', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'percent'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.percent-percent`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.percent`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + // TODO: percent 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数点不应该被去掉; + test.fail(); + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'percent'), + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).toHaveValue(String(record.percent)); + + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.percent-percent') + .getByRole('spinbutton') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.percent-percent') + .getByRole('spinbutton') + .fill('11.22'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.percent-percent')).toHaveText( + 'percent:11.22%', + ); + }, + }); + }); + + test('set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'percent'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.percent-percent`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.percent`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'percent'); + await showSettingsMenu(page, 'percent'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaSettings.test.ts new file mode 100644 index 000000000..c28f32e6e --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/phone/schemaSettings.test.ts @@ -0,0 +1,224 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.phone-phone`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.phone`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'phone'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: '17777777777', + variableValue: ['Current user', 'ID'], // 值为 1 + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).toHaveValue('17777777777'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).toHaveValue('1'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'phone'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.phone-phone') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.phone-phone') + .getByRole('textbox') + .fill('17777777777'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone-phone')).toHaveText( + 'phone:17777777777', + ); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.phone-phone`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.phone`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + record = await mockRecord('general'); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.phone-phone`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.phone`) + .hover(); + }, + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.phone-phone') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.phone-phone') + .getByRole('textbox') + .fill('17777777777'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone-phone')).toHaveText( + 'phone:17777777777', + ); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.phone-phone`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.phone`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'phone'); + await showSettingsMenu(page, 'phone'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaSettings.test.ts new file mode 100644 index 000000000..564012ac8 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/radioGroup/schemaSettings.test.ts @@ -0,0 +1,241 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.radioGroup-radioGroup`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.radioGroup`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'radioGroup'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByLabel('Option2').click(); + }, + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2'), + ).toBeChecked(); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'radioGroup'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2') + .click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup'), + ).toHaveText('radioGroup:Option2'); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.radioGroup-radioGroup`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.radioGroup`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'radioGroup'), + expectEditable: async () => { + if (record.radioGroup) { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel(record.radioGroup), + ).toBeChecked(); + } + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') + .getByLabel('Option2'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup'), + ).toHaveText(`radioGroup:${record.radioGroup}`, { ignoreCase: true }); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.radioGroup-radioGroup`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.radioGroup`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'radioGroup'); + await showSettingsMenu(page, 'radioGroup'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaSettings.test.ts new file mode 100644 index 000000000..42b915605 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/richText/schemaSettings.test.ts @@ -0,0 +1,281 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndMediaFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.richText-richText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Delete', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord }) => { + await testDefaultValue({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.richText-richText`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`, { + exact: true, + }) + .hover(); + }, + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-CollectionField-general-general.richText').locator('.ql-editor').click(); + await page.keyboard.type('test rich text'); + }, + expectConstantValue: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( + /test rich text/, + ); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.richText-richText`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`, { + exact: true, + }) + .hover(); + }, + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.richText-richText') + .locator('.ql-editor') + .click(); + await page.keyboard.type('test rich text pattern'); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), + ).toHaveClass(/ql-disabled/); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( + /test rich text pattern/, + ); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: async () => { + await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + showMenu: async () => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, { + exact: true, + }) + .hover(); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.richText-richText`, { exact: true }).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`, { + exact: true, + }) + .hover(); + + await expectSettingsMenu({ + page, + showMenu: async () => {}, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'richText'), + expectEditable: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-editor'), + ).toHaveText(record.richText); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), + ).toHaveClass(/ql-disabled/); + }, + expectEasyReading: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( + `richText:${record.richText}`, + ); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'markdown'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + // 等待页面稳定 + await page.waitForTimeout(1000); + await page.getByLabel(`block-item-CollectionField-general-form-general.richText-richText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'richText'); + await showSettingsMenu(page, 'richText'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaSettings.test.ts new file mode 100644 index 000000000..29900fe72 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/sequence/schemaSettings.test.ts @@ -0,0 +1,79 @@ +import { expectSettingsMenu, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.sequence-sequence`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.sequence`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Pattern', 'Delete', 'required'], + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.sequence-sequence`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.sequence`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.sequence-sequence`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.sequence`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'sequence'); + await showSettingsMenu(page, 'sequence'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaSettings.test.ts new file mode 100644 index 000000000..3d2615de9 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleLineText/schemaSettings.test.ts @@ -0,0 +1,376 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.singleLineText-singleLineText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleLineText`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + 'Set validation rules', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'singleLineText'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'test single line text', + variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com + expectConstantValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).toHaveValue('test single line text'); + }, + expectVariableValue: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).toHaveValue('admin@nocobase.com'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'singleLineText'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox') + .click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox') + .fill('test single line text'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText'), + ).toHaveText('singleLineText:test single line text'); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'singleLineText'), + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.singleLineText-singleLineText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleLineText`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set validation rules', + 'Pattern', + 'Delete', + ], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'singleLineText'), + expectEditable: async () => { + // 应该显示 record 中的值 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).toHaveValue(record.singleLineText); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') + .getByRole('textbox'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText'), + ).toHaveText(`singleLineText:${record.singleLineText}`); + }, + }); + }); + + test('Set validation rules', async ({ page, mockPage, mockRecord }) => { + await testSetValidationRules({ + page, + gotoPage: () => + (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord), + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'singleLineText'), + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.singleLineText-singleLineText`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleLineText`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'singleLineText'); + await showSettingsMenu(page, 'singleLineText'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); + + test('custom column title', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecords('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'singleLineText'); + await showSettingsMenu(page, 'singleLineText'); + await page.getByRole('menuitem', { name: 'Custom column title' }).click(); + + // 显示出原字段名称 + await expect(page.getByRole('dialog').getByText('Original field title: singleLineText')).toBeVisible(); + // 输入新字段名称 + await page.getByLabel('block-item-Input-general-column title').getByRole('textbox').click(); + await page.getByLabel('block-item-Input-general-column title').getByRole('textbox').fill('new column title'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 新名称应该显示出来 + await expect(page.getByRole('button', { name: 'new column title', exact: true })).toBeVisible(); + }); + + test('column width', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecords('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'singleLineText'); + await showSettingsMenu(page, 'singleLineText'); + await page.getByRole('menuitem', { name: 'Column width' }).click(); + await page.getByRole('dialog').getByRole('spinbutton').click(); + await page.getByRole('dialog').getByRole('spinbutton').fill('600'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + const columnHeadSize = await page.getByRole('columnheader', { name: 'singleLineText' }).boundingBox(); + expect(Math.floor(columnHeadSize.width)).toBe(600); + }); + + test('sortable', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecords('general', [{ singleLineText: 'a' }, { singleLineText: 'b' }]); + await nocoPage.goto(); + + await createColumnItem(page, 'singleLineText'); + await showSettingsMenu(page, 'singleLineText'); + + // 默认不可排序 + await expect(page.getByRole('menuitem', { name: 'Sortable' }).getByRole('switch')).not.toBeChecked(); + + // 开启排序 + await page.getByRole('menuitem', { name: 'Sortable' }).click(); + // TODO: 此处菜单在点击后不应该消失 + // await expect(page.getByRole('menuitem', { name: 'Sortable' }).getByRole('switch')).toBeChecked(); + + // 鼠标 hover 时,有提示 + await page.getByRole('columnheader', { name: 'singleLineText' }).hover(); + await expect(page.getByRole('tooltip', { name: 'Click to sort ascending' })).toBeVisible(); + + // 点击第一下,升序 + await page.getByRole('columnheader', { name: 'singleLineText' }).click(); + let sizeA = await page.getByRole('cell', { name: 'a', exact: true }).boundingBox(); + let sizeB = await page.getByRole('cell', { name: 'b', exact: true }).boundingBox(); + expect(sizeA.y).toBeLessThan(sizeB.y); + + // 点击第二下,降序 + await page.getByRole('columnheader', { name: 'singleLineText' }).click(); + sizeA = await page.getByRole('cell', { name: 'a', exact: true }).boundingBox(); + sizeB = await page.getByRole('cell', { name: 'b', exact: true }).boundingBox(); + expect(sizeA.y).toBeGreaterThan(sizeB.y); + }); + + test('delete', async ({ page, mockPage, mockRecords }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecords('general'); + await nocoPage.goto(); + + await createColumnItem(page, 'singleLineText'); + await showSettingsMenu(page, 'singleLineText'); + await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await expect(page.getByRole('columnheader', { name: 'singleLineText' })).toBeHidden(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaSettings.test.ts new file mode 100644 index 000000000..a29de03af --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/singleSelect/schemaSettings.test.ts @@ -0,0 +1,239 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.singleSelect-singleSelect`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleSelect`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'singleSelect'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').click(); + await page.getByRole('option', { name: 'Option1' }).click(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), + ).toHaveText('singleSelect:Option1'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'singleSelect'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single') + .click(); + await page.getByRole('option', { name: 'Option1' }).click(); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single'), + ).toHaveClass(/ant-select-disabled/); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), + ).toHaveText('singleSelect:Option1'); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page + .getByLabel(`block-item-CollectionField-general-form-general.singleSelect-singleSelect`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleSelect`, { + exact: true, + }) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page + .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) + .hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { + exact: true, + }) + .hover(); + })(page, 'singleSelect'), + expectEditable: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single'), + ).toHaveText(record.singleSelect, { ignoreCase: true }); + }, + expectReadonly: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single'), + ).toHaveClass(/ant-select-disabled/); + }, + expectEasyReading: async () => { + await expect( + page + .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') + .getByTestId('select-single'), + ).not.toBeVisible(); + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), + ).toHaveText(`singleSelect:${record.singleSelect}`, { ignoreCase: true }); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.singleSelect-singleSelect`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.singleSelect`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'singleSelect'); + await showSettingsMenu(page, 'singleSelect'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaSettings.test.ts new file mode 100644 index 000000000..4c1c80b1c --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/tableOID/schemaSettings.test.ts @@ -0,0 +1,136 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.tableoid-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.tableoid`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await nocoPage.goto(); + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.tableoid-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.tableoid`) + .hover(); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.tableoid-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.tableoid`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit tooltip', 'Pattern', 'Delete'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'tableoid'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.tableoid-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.tableoid`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('options', async ({ page, mockPage, mockRecord }) => { + await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + await (async (page: Page) => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + })(page); + await (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'tableoid'); + await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'Table OID'); + await showSettingsMenu(page, 'Table OID'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaInitializer.test.ts new file mode 100644 index 000000000..2d3f41aef --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaInitializer.test.ts @@ -0,0 +1,21 @@ +import { test } from '@nocobase/test/e2e'; + +test('form item & create form', async ({ page, mockPage }) => {}); + +test('form item & edit form', async ({ page, mockPage }) => {}); + +test('form item & view form', async ({ page, mockPage }) => {}); + +test('form item & filter form', async ({ page, mockPage }) => {}); + +test('table column & table', async ({ page, mockPage }) => {}); + +test('table column & table & record picker', async ({ page, mockPage }) => {}); + +test('table column & table & Relationship block', async ({ page, mockPage }) => {}); + +test('table column & sub table & create from', async ({ page, mockPage }) => {}); + +test('table column & sub table & edit from', async ({ page, mockPage }) => {}); + +test('table column & sub table & view from', async ({ page, mockPage }) => {}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaSettings.test.ts new file mode 100644 index 000000000..2f8e7626b --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/time/schemaSettings.test.ts @@ -0,0 +1,208 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, + test, +} from '@nocobase/test/e2e'; +import dayjs from 'dayjs'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.time-time`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.time`) + .hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Required', + 'Set default value', + 'Pattern', + 'Delete', + ], + }); + }); + + test('set default value', async ({ page, mockPage, mockRecord }) => { + let nowTime; + await testDefaultValue({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + }, + closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.time-time`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.time`) + .hover(); + }, + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + inputConstantValue: async () => { + await page.getByLabel('block-item-VariableInput-').getByPlaceholder('Select time').click(); + await page.getByText('Now').click(); + nowTime = dayjs(); + }, + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), + ).toHaveValue(new RegExp(nowTime.format('HH:mm:ss'))); + }, + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'time'), + expectEditable: async () => { + await page + .getByLabel('block-item-CollectionField-general-form-general.time-time') + .getByPlaceholder('Select time') + .click(); + await page.getByText('Now').click(); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.time-time')).toHaveText( + new RegExp(`time:${dayjs().format('HH:mm:')}`), + ); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.time-time`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.time`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + unsupportedOptions: ['Set default value'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record = null; + await testPattern({ + page, + gotoPage: async () => { + record = await (async (mockPage, mockRecord) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + const record = await mockRecord('general'); + await nocoPage.goto(); + + return record; + })(mockPage, mockRecord); + }, + openDialog: () => + (async (page: Page) => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'time'), + expectEditable: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), + ).toHaveValue(record.time); + }, + expectReadonly: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + await expect(page.getByLabel('block-item-CollectionField-general-form-general.time-time')).toHaveText( + new RegExp(`time:${record.time}`), + ); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.time-time`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.time`) + .hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'time'); + await showSettingsMenu(page, 'time'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Sortable', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaInitializer.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaSettings.test.ts new file mode 100644 index 000000000..de10b8c27 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/url/schemaSettings.test.ts @@ -0,0 +1,212 @@ +import { + Page, + expect, + expectSettingsMenu, + oneTableBlockWithAddNewAndViewAndEditAndBasicFields, + test, +} from '@nocobase/test/e2e'; +import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils'; + +test.describe('form item & create form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByRole('button', { name: 'Add new' }).click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.url-url`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.url`).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Display title', + 'Edit description', + 'Pattern', + 'Delete', + 'required', + 'Set default value', + ], + }); + }); + + test('set default value', async ({ page, mockPage }) => { + await testDefaultValue({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + closeDialog: async () => { + await page.getByLabel('drawer-Action.Container-general-Add record-mask').click(); + }, + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'url'), + supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], + constantValue: 'https://nocobase.com', + variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com + expectConstantValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).toHaveValue('https://nocobase.com'); + }, + expectVariableValue: async () => { + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).toHaveValue('admin@nocobase.com'); + }, + }); + }); + + test('pattern', async ({ page, mockPage }) => { + await testPattern({ + page, + gotoPage: () => + (async (mockPage) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await nocoPage.goto(); + })(mockPage), + openDialog: () => + (async (page: Page) => { + await page.getByRole('button', { name: 'Add new' }).click(); + })(page), + showMenu: () => + (async (page: Page, fieldName: string) => { + await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); + await page + .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) + .hover(); + })(page, 'url'), + expectEditable: async () => { + // 默认情况下可以编辑 + await page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox').click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.url-url') + .getByRole('textbox') + .fill('https://nocobase.com'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // 输入框会消失,只剩下值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText( + 'url:https://nocobase.com', + ); + }, + }); + }); +}); + +test.describe('form item & edit form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.url-url`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.url`).hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Edit description', 'Required', 'Pattern', 'Delete'], + }); + }); + + test('pattern', async ({ page, mockPage, mockRecord }) => { + let record: any = null; + await testPattern({ + page, + gotoPage: async () => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + record = await mockRecord('general'); + await nocoPage.goto(); + }, + openDialog: async () => { + await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); + }, + showMenu: async () => { + await page.getByLabel(`block-item-CollectionField-general-form-general.url-url`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.url`).hover(); + }, + expectEditable: async () => { + // 默认情况下可以编辑 + await page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox').click(); + await page + .getByLabel('block-item-CollectionField-general-form-general.url-url') + .getByRole('textbox') + .fill('https://nocobase.com'); + }, + expectReadonly: async () => { + // 只读模式下,输入框会被禁用 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).toBeDisabled(); + }, + expectEasyReading: async () => { + // url 类型数据不会被 mock,所以这里不会显示值 + await expect( + page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), + ).not.toBeVisible(); + await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText( + 'url:https://nocobase.com', + ); + }, + }); + }); +}); + +test.describe('form item & view form', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); + await page.getByLabel(`block-item-CollectionField-general-form-general.url-url`).hover(); + await page.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.url`).hover(); + }, + supportedOptions: ['Edit field title', 'Display title', 'Delete', 'Edit tooltip'], + unsupportedOptions: ['Set default value'], + }); + }); +}); + +test.describe('table column & table', () => { + test('supported options', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); + await mockRecord('general'); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await createColumnItem(page, 'url'); + await showSettingsMenu(page, 'url'); + }, + supportedOptions: ['Custom column title', 'Column width', 'Delete'], + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/commonTesting.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/commonTesting.ts deleted file mode 100644 index 4c11f4177..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/commonTesting.ts +++ /dev/null @@ -1,278 +0,0 @@ -import { Page, expect, test } from '@nocobase/test/e2e'; - -export async function testEditFieldTitle(page: Page) { - await page.getByRole('menuitem', { name: 'Edit field title' }).click(); - await page.getByLabel('block-item-Input-general-').getByRole('textbox').click(); - await page.getByLabel('block-item-Input-general-').getByRole('textbox').fill('testing edit field title'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - await expect(page.getByText('testing edit field title')).toBeVisible(); -} - -export async function testDisplayTitle(page: Page, title: string) { - // 默认情况下是开启状态 - await expect(page.getByRole('menuitem', { name: 'Display title' }).getByRole('switch')).toBeChecked(); - await page.getByRole('menuitem', { name: 'Display title' }).click(); - await expect(page.getByRole('menuitem', { name: 'Display title' }).getByRole('switch')).not.toBeChecked(); - await expect(page.getByText(`${title}:`, { exact: true })).not.toBeVisible(); -} - -export async function testEditDescription(page: Page) { - await page.getByRole('menuitem', { name: 'Edit description' }).click(); - await page.getByLabel('block-item-Input.TextArea-').getByRole('textbox').click(); - await page.getByLabel('block-item-Input.TextArea-').getByRole('textbox').fill('testing edit description'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - await expect(page.getByText('testing edit description')).toBeVisible(); -} -export async function testRequired(page: Page) { - // 默认情况下是关闭状态 - await expect(page.getByRole('menuitem', { name: 'Required' }).getByRole('switch')).not.toBeChecked(); - await page.getByRole('menuitem', { name: 'Required' }).click(); - await expect(page.getByRole('menuitem', { name: 'Required' }).getByRole('switch')).toBeChecked(); -} - -export async function clickDeleteAndOk(page: Page) { - await page.getByRole('menuitem', { name: 'Delete' }).click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); -} - -export const commonTesting = ({ - openDialogAndShowMenu, - fieldName, - blockType = 'creating', - fieldType, - mode = 'details', -}: { - openDialogAndShowMenu: ({ - page, - mockPage, - mockRecord, - mockRecords, - fieldName, - }: { - page: Page; - mockPage: any; - mockRecord: any; - mockRecords: any; - fieldName: string; - }) => Promise; - fieldName: string; - blockType?: 'creating' | 'viewing' | 'editing'; - fieldType?: 'relation' | 'system'; - /** - * options 模式下,只会测试选项是否正确显示; - * details 模式下,会测试每个选项的功能是否正常; - */ - mode?: 'options' | 'details'; -}) => { - if (mode === 'details') { - test('edit field title', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await testEditFieldTitle(page); - }); - - test('display title', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await testDisplayTitle(page, fieldName); - }); - - test('delete', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await clickDeleteAndOk(page); - await expect(page.getByText(`${fieldName}:`)).not.toBeVisible(); - }); - - if (['creating', 'editing'].includes(blockType)) { - test('edit description', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await testEditDescription(page); - }); - - test('required', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await testRequired(page); - }); - } - - if (blockType === 'viewing') { - test('edit tooltip', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await page.getByRole('menuitem', { name: 'Edit tooltip' }).click(); - await page.getByRole('dialog').getByRole('textbox').click(); - await page.getByRole('dialog').getByRole('textbox').fill('testing edit tooltip'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - await page.getByRole('img', { name: 'question-circle' }).hover(); - await expect(page.getByText('testing edit tooltip')).toBeVisible(); - }); - } - } - - if (mode === 'options') { - test('should display correct options', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName }); - await expect(page.getByRole('menuitem', { name: 'Edit field title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Display title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Delete' })).toBeVisible(); - if (['creating', 'editing'].includes(blockType) && fieldType !== 'system') { - await expect(page.getByRole('menuitem', { name: 'Edit description' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Required' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).toBeVisible(); - } - if (blockType === 'viewing') { - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).not.toBeVisible(); - } - if ( - blockType === 'creating' && - !fieldName.startsWith('oneTo') && - !['attachment'].includes(fieldName) && - !['system'].includes(fieldType) - ) { - await expect(page.getByRole('menuitem', { name: 'Set default value' })).toBeVisible(); - } - if (['editing', 'viewing'].includes(blockType)) { - await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); - } - if (fieldType === 'relation' && ['creating', 'editing'].includes(blockType)) { - await expect(page.getByRole('menuitem', { name: 'Set default sorting rules' })).toBeVisible(); - } - }); - } -}; - -export async function testDefaultValue({ - page, - openDialog, - closeDialog, - gotoPage, - showMenu, - supportVariables, - constantValue, - variableValue, - inputConstantValue, - expectConstantValue, - expectVariableValue, -}: { - page: Page; - openDialog: () => Promise; - closeDialog: () => Promise; - gotoPage: () => Promise; - showMenu: () => Promise; - /** 支持的变量列表,如:['Current user', 'Date variables', 'Current form'] */ - supportVariables: string[]; - /** 常量默认值 */ - constantValue?: string | number; - /** 变量默认值 */ - variableValue?: string[]; - /** 输入常量默认值 */ - inputConstantValue?: () => Promise; - /** 对常量默认值进行断言 */ - expectConstantValue?: () => Promise; - /** 对变量默认值进行断言 */ - expectVariableValue?: () => Promise; -}) { - await gotoPage(); - await openDialog(); - await showMenu(); - - if (constantValue || inputConstantValue) { - // 设置一个常量作为默认值 - await page.getByRole('menuitem', { name: 'Set default value' }).click(); - if (inputConstantValue) { - await inputConstantValue(); - } else { - await page.getByLabel('block-item-VariableInput-').getByRole('textbox').click(); - await page.getByLabel('block-item-VariableInput-').getByRole('textbox').fill(String(constantValue)); - } - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 关闭弹窗,然后再次打开后,应该显示刚才设置的默认值 - await closeDialog(); - await openDialog(); - await expectConstantValue(); - } - - if (variableValue) { - // 设置一个变量作为默认值 - await showMenu(); - await page.getByRole('menuitem', { name: 'Set default value' }).click(); - await page.getByLabel('variable-button').click(); - for (const value of supportVariables) { - await expect(page.getByRole('menuitemcheckbox', { name: value })).toBeVisible(); - } - for (const value of variableValue) { - await page.getByRole('menuitemcheckbox', { name: value }).click(); - } - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - await closeDialog(); - await openDialog(); - await expectVariableValue(); - } -} - -export async function testPattern({ - page, - gotoPage, - openDialog, - showMenu, - expectEditable, - expectReadonly, - expectEasyReading, -}: { - page: Page; - gotoPage: () => Promise; - openDialog: () => Promise; - showMenu: () => Promise; - /** 断言选项为 Editable 的情况 */ - expectEditable: () => Promise; - /** 断言选项为 Readonly 的情况 */ - expectReadonly: () => Promise; - /** 断言选项为 Easy-reading 的情况 */ - expectEasyReading: () => Promise; -}) { - await gotoPage(); - await openDialog(); - - // 默认情况下,显示的是 Editable - await expectEditable(); - await showMenu(); - await expect(page.getByText('PatternEditable')).toBeVisible(); - - // 更改为 Readonly - await page.getByRole('menuitem', { name: 'Pattern' }).click(); - await page.getByRole('option', { name: 'Readonly' }).click(); - await expectReadonly(); - - // 更改为 Easy-reading - await showMenu(); - await expect(page.getByText('PatternReadonly')).toBeVisible(); - await page.getByRole('menuitem', { name: 'Pattern' }).click(); - await page.getByRole('option', { name: 'Easy-reading' }).click(); - await expectEasyReading(); - - await showMenu(); - await expect(page.getByText('PatternEasy-reading')).toBeVisible(); -} - -export async function testSetValidationRules({ - page, - gotoPage, - openDialog, - showMenu, -}: { - page: Page; - gotoPage: () => Promise; - openDialog: () => Promise; - showMenu: () => Promise; -}) { - await gotoPage(); - await openDialog(); - await showMenu(); - - await page.getByRole('menuitem', { name: 'Set validation rules' }).click(); - await expect(page.getByRole('dialog').getByText('Set validation rules')).toBeVisible(); - - // TODO: 更详细的测试 -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/advanced.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/advanced.test.ts deleted file mode 100644 index 82a283cc1..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/advanced.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Page, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('collection', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'collection', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('JSON', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'JSON', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('formula', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'formula', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('sequence', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'sequence', blockType: 'viewing', mode: 'options' }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); - await mockRecord('general'); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/basic.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/basic.test.ts deleted file mode 100644 index e9cb8abf2..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/basic.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Page, oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('color', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'color', blockType: 'viewing' }); -}); - -test.describe('email', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'email', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('icon', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'icon', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('single line text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleLineText', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('integer', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'integer', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('number', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'number', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('password', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'password', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('percent', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'percent', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('phone', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'phone', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('long text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'longText', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('URL', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'url', blockType: 'viewing', mode: 'options' }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/choices.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/choices.test.ts deleted file mode 100644 index 3cb1a4009..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/choices.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Page, oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('checkbox', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkbox', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('checkbox group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkboxGroup', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('china region', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'chinaRegion', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('multiple select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'multipleSelect', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('radio group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'radioGroup', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('single select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleSelect', blockType: 'viewing', mode: 'options' }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/datetime.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/datetime.test.ts deleted file mode 100644 index d0ba2c1aa..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/datetime.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, test } from '@nocobase/test/e2e'; -import dayjs from 'dayjs'; -import { commonTesting } from '../commonTesting'; - -test.describe('datetime', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'datetime', blockType: 'viewing', mode: 'options' }); - - test('date display format', async ({ page, mockPage, mockRecord }) => { - const record = await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'datetime' }); - await page.getByRole('menuitem', { name: 'Date display format' }).click(); - await page.getByLabel('YYYY/MM/DD').click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( - `datetime:${dayjs(record.datetime).format('YYYY/MM/DD')}`, - ); - }); -}); - -test.describe('time', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'time', blockType: 'viewing', mode: 'options' }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - const record = await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); - - return record; -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/media.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/media.test.ts deleted file mode 100644 index 4de506412..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/media.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndMediaFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('markdown', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'markdown', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('rich text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'richText', blockType: 'viewing', mode: 'options' }); -}); - -test.describe('attachment', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'attachment', blockType: 'viewing', mode: 'options' }); - - test('size', async ({ page, mockPage, mockRecord }) => { - const record = await gotoPage(mockPage, mockRecord); - await openDialog(page); - - // 默认尺寸 - // 这里的尺寸不稳定,所以用 try catch 来处理 - const testDefault = async (value) => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first(), - ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); - }; - try { - await testDefault(94); - } catch (error) { - try { - await testDefault(95); - } catch (err) { - await testDefault(96); - } - } - - // 改为大尺寸 - const testLarge = async (value) => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first(), - ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); - }; - await showMenu(page, 'attachment'); - await page.getByRole('menuitem', { name: 'Size' }).click(); - await page.getByRole('option', { name: 'Large' }).click(); - try { - await testLarge(153); - } catch (err) { - try { - await testLarge(154); - } catch (err) { - await testLarge(152); - } - } - - // 改为小尺寸 - const testSmall = async (value) => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first(), - ).toHaveJSProperty('offsetWidth', value, { timeout: 1000 }); - }; - await showMenu(page, 'attachment'); - await page.getByRole('menuitem', { name: 'Size' }).click(); - await page.getByRole('option', { name: 'Small' }).click(); - try { - await testSmall(25); - } catch (err) { - try { - await testSmall(26); - } catch (err) { - await testSmall(24); - } - } - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - // 这里是为了等弹窗中的内容渲染稳定后,再去 hover,防止错位导致测试报错 - await page.waitForTimeout(1000); - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/relation.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/relation.test.ts deleted file mode 100644 index f032e943e..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/relation.test.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('many to many', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'manyToMany', - fieldType: 'relation', - mode: 'options', - blockType: 'viewing', - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); - - test('enable link', async ({ page, mockPage, mockRecords }) => { - // test.fail(); - const record = await gotoPage(mockPage, mockRecords); - await openDialog(page); - - // 初始状态是一个可点击的链接 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .locator('a') - .filter({ hasText: record.manyToMany[0].id }), - ).toBeVisible(); - - await showMenu(page, 'manyToMany'); - - // 默认情况下是开启状态 - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - await page.getByRole('menuitem', { name: 'Enable link' }).click(); - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked(); - - // 应变为非链接状态 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .locator('a') - .filter({ hasText: record.manyToMany[0].id }), - ).not.toBeVisible(); - - // 再次开启链接状态 - await page.getByRole('menuitem', { name: 'Enable link' }).click(); - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .locator('a') - .filter({ hasText: record.manyToMany[0].id }), - ).toBeVisible(); - }); -}); - -test.describe('many to one', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'manyToOne', - fieldType: 'relation', - mode: 'options', - blockType: 'viewing', - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); - - test('enable link', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - }); -}); - -test.describe('one to many', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToMany', - fieldType: 'relation', - mode: 'options', - blockType: 'viewing', - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); - - test('enable link', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - }); -}); - -test.describe('one to one (belongs to)', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToOneBelongsTo', - fieldType: 'relation', - mode: 'options', - blockType: 'viewing', - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); - - test('enable link', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - }); -}); - -test.describe('one to one (has one)', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToOneHasOne', - fieldType: 'relation', - mode: 'options', - blockType: 'viewing', - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); - - test('enable link', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - }); -}); - -const gotoPage = async (mockPage, mockRecords) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const record = (await mockRecords('general', 1))[0]; - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecords, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - mockRecords; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/systemInfo.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/systemInfo.test.ts deleted file mode 100644 index d4c269767..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/details-single-data/systemInfo.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('created at', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'createdAt', - fieldType: 'system', - mode: 'options', - blockType: 'viewing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdAt' }); - await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); - }); -}); -test.describe('created by', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'createdBy', - fieldType: 'system', - mode: 'options', - blockType: 'viewing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdBy' }); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); -test.describe('id', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'id', fieldType: 'system', mode: 'options', blockType: 'viewing' }); -}); -test.describe('table oid', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'tableoid', - fieldType: 'system', - mode: 'options', - blockType: 'viewing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'tableoid' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('last updated at', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'updatedAt', - fieldType: 'system', - mode: 'options', - blockType: 'viewing', - }); -}); -test.describe('last updated by', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'updatedBy', - fieldType: 'system', - mode: 'options', - blockType: 'viewing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'updatedBy' }); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-View record-view-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/advanced.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/advanced.test.ts deleted file mode 100644 index 45b26a321..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/advanced.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('collection', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'collection', mode: 'options' }); -}); -test.describe('JSON', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'JSON', mode: 'options' }); -}); -test.describe('formula', () => { - test('should display correct options', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'formula' }); - await expect(page.getByRole('menuitem', { name: 'Edit field title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Display title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Delete' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('sequence', () => { - test('should display correct options', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'sequence' }); - await expect(page.getByRole('menuitem', { name: 'Edit field title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Display title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Delete' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Edit description' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'required' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/basic.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/basic.test.ts deleted file mode 100644 index b46bef4a8..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/basic.test.ts +++ /dev/null @@ -1,750 +0,0 @@ -import { expect, oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testDefaultValue, testPattern, testSetValidationRules } from '../commonTesting'; - -test.describe('color', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'color' }); - - test('set default value', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'color' }); - // 简单测试下是否有选项,值的话无法选中,暂时测不了 - await expect(page.getByRole('menuitem', { name: 'Set default value' })).toBeVisible(); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'color'), - expectEditable: async () => { - // 默认情况下显示颜色选择框 - await page.getByLabel('color-picker-normal').hover(); - await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).toBeVisible(); - }, - expectReadonly: async () => { - // 只读模式下,不会显示颜色弹窗 - await page.getByLabel('color-picker-normal').hover(); - await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).not.toBeVisible(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('color-picker-read-pretty')).toBeVisible(); - }, - }); - }); -}); - -test.describe('email', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'email', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'email'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'test@nocobase.com', - variableValue: ['Current user', 'Email'], - expectConstantValue: () => - expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).toHaveValue('test@nocobase.com'), - expectVariableValue: () => - expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).toHaveValue('admin@nocobase.com'), - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'email'), - expectEditable: async () => { - // 填充一个值,方便后面断言 - await page - .getByLabel('block-item-CollectionField-general-form-general.email-email') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.email-email') - .getByRole('textbox') - .fill('admin@nocobase.com'); - }, - expectReadonly: async () => { - // 输入框应该被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框应该消失,直接显示值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.email-email')).toHaveText( - 'email:admin@nocobase.com', - ); - }, - }); - }); -}); - -test.describe('icon', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'icon', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'icon'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByRole('button', { name: 'Select icon' }).click(); - await page.getByLabel('account-book').locator('svg').click(); - }, - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.icon-icon') - .getByRole('button', { name: 'account-book' }), - ).toBeVisible(); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'icon'), - expectEditable: async () => { - // 默认情况下可以编辑图标 - await page.getByRole('button', { name: 'Select icon' }).click(); - await page.getByLabel('account-book').locator('svg').click(); - }, - expectReadonly: async () => { - // 只读模式下,选择图标按钮会被禁用 - await expect(page.getByRole('button', { name: 'account-book' })).toBeDisabled(); - }, - expectEasyReading: async () => { - // 按钮会消失,只剩下图标 - await expect(page.getByRole('button', { name: 'account-book' })).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.icon-icon').getByLabel('account-book'), - ).toBeVisible(); - }, - }); - }); -}); - -test.describe('single line text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleLineText', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'singleLineText'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'test single line text', - variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).toHaveValue('test single line text'); - }, - expectVariableValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).toHaveValue('admin@nocobase.com'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleLineText'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox') - .fill('test single line text'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText'), - ).toHaveText('singleLineText:test single line text'); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleLineText'), - }); - }); -}); - -test.describe('integer', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'integer', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'integer'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - variableValue: ['Current user', 'ID'], // 值为 1 - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('112233'); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).toHaveValue('112233'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).toHaveValue('1'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'integer'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.integer-integer') - .getByRole('spinbutton') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.integer-integer') - .getByRole('spinbutton') - .fill('112233'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText( - 'integer:112233', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'integer'), - }); - }); -}); - -test.describe('number', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'number', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'number'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('11.22'); - }, - variableValue: ['Current user', 'ID'], // 值为 1 - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).toHaveValue('11.22'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).toHaveValue('1'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - // TODO: number 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数不应该被去掉; - test.fail(); - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'number'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.number-number') - .getByRole('spinbutton') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.number-number') - .getByRole('spinbutton') - .fill('11.22'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.number-number')).toHaveText( - 'number:11.22', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'number'), - }); - }); -}); - -test.describe('password', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'password', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'password'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'test112233password', - variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).toHaveValue('test112233password'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).toHaveValue('admin@nocobase.com'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'password'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.password-password') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.password-password') - .getByRole('textbox') - .fill('test112233password'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.password-password')).toHaveText( - 'password:********', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'password'), - }); - }); -}); - -test.describe('percent', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'percent', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'percent'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').click(); - await page.getByLabel('block-item-VariableInput-').getByRole('spinbutton').fill('11.22'); - }, - variableValue: ['Current user', 'ID'], // 值为 1 - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).toHaveValue('11.22'); - }, - expectVariableValue: async () => { - // 数字 1 转换为百分比后为 100% - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).toHaveValue('100'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - // TODO: percent 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数点不应该被去掉; - test.fail(); - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'percent'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.percent-percent') - .getByRole('spinbutton') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.percent-percent') - .getByRole('spinbutton') - .fill('11.22'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.percent-percent')).toHaveText( - 'percent:11.22%', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'percent'), - }); - }); -}); - -test.describe('phone', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'phone', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'phone'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: '17777777777', - variableValue: ['Current user', 'ID'], // 值为 1 - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).toHaveValue('17777777777'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).toHaveValue('1'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'phone'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.phone-phone') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.phone-phone') - .getByRole('textbox') - .fill('17777777777'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone-phone')).toHaveText( - 'phone:17777777777', - ); - }, - }); - }); -}); - -test.describe('long text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'longText', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: async () => { - await page.getByLabel('drawer-Action.Container-general-Add record-mask').click(); - }, - showMenu: () => showMenu(page, 'longText'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'test long text', - variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).toHaveValue('test long text'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).toHaveValue('admin@nocobase.com'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'longText'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.longText-longText') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.longText-longText') - .getByRole('textbox') - .fill('test long text'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.longText-longText')).toHaveText( - 'longText:test long text', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'longText'), - }); - }); -}); - -test.describe('URL', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'url', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: async () => { - await page.getByLabel('drawer-Action.Container-general-Add record-mask').click(); - }, - showMenu: () => showMenu(page, 'url'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'https://nocobase.com', - variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).toHaveValue('https://nocobase.com'); - }, - expectVariableValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).toHaveValue('admin@nocobase.com'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'url'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox').click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.url-url') - .getByRole('textbox') - .fill('https://nocobase.com'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText( - 'url:https://nocobase.com', - ); - }, - }); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/choices.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/choices.test.ts deleted file mode 100644 index 0ee5eb846..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/choices.test.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testDefaultValue, testPattern } from '../commonTesting'; - -test.describe('checkbox', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkbox', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'checkbox'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - // 默认应该是没有被选中的,点击后应该被选中 - await page.getByLabel('block-item-VariableInput-').getByRole('checkbox').click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).toBeChecked(); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'checkbox'), - expectEditable: async () => { - // 默认是未选中的状态,所以先选中 - await page - .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') - .getByRole('checkbox') - .click(); - }, - expectReadonly: async () => { - // checkbox 应该被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // checkbox 应该被隐藏,然后只显示一个图标 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).not.toBeVisible(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') - .getByRole('img', { name: 'check' }), - ).toBeVisible(); - }, - }); - }); -}); - -test.describe('checkbox group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkboxGroup', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'checkboxGroup'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByLabel('Option1').click(); - }, - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }), - ).toBeChecked(); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'checkboxGroup'), - expectEditable: async () => { - // 默认是未选中的状态,所以先选中 - await page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }) - .click(); - }, - expectReadonly: async () => { - // checkbox 应该被禁用 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // checkbox 应该被隐藏,然后只显示一个标签 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }), - ).not.toBeVisible(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByText('Option1'), - ).toBeVisible(); - }, - }); - }); -}); - -test.describe('china region', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'chinaRegion', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'chinaRegion'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').click(); - await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); - await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); - await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), - ).toHaveText('chinaRegion:北京市/市辖区/东城区'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'chinaRegion'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .click(); - await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); - await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); - await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .getByRole('combobox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .getByRole('combobox'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), - ).toHaveText('chinaRegion:北京市 / 市辖区 / 东城区'); - }, - }); - }); -}); - -test.describe('multiple select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'multipleSelect', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'multipleSelect'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByTestId('select-multiple').click(); - await page.getByRole('option', { name: 'Option1' }).click(); - await page.getByRole('option', { name: 'Option2' }).click(); - await page.getByRole('option', { name: 'Option3' }).click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), - ).toHaveText('multipleSelect:Option1Option2Option3'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'multipleSelect'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple') - .click(); - await page.getByRole('option', { name: 'Option1' }).click(); - await page.getByRole('option', { name: 'Option2' }).click(); - await page.getByRole('option', { name: 'Option3' }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple'), - ).toHaveClass(/ant-select-disabled/); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), - ).toHaveText('multipleSelect:Option1Option2Option3'); - }, - }); - }); -}); - -test.describe('radio group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'radioGroup', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'radioGroup'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByLabel('Option2').click(); - }, - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2'), - ).toBeChecked(); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'radioGroup'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2') - .click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup'), - ).toHaveText('radioGroup:Option2'); - }, - }); - }); -}); - -test.describe('single select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleSelect', mode: 'options' }); - - test('set default value', async ({ page, mockPage }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'singleSelect'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').click(); - await page.getByRole('option', { name: 'Option1' }).click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), - ).toHaveText('singleSelect:Option1'); - }, - }); - }); - - test('pattern', async ({ page, mockPage }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleSelect'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single') - .click(); - await page.getByRole('option', { name: 'Option1' }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single'), - ).toHaveClass(/ant-select-disabled/); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), - ).toHaveText('singleSelect:Option1'); - }, - }); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/datetime.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/datetime.test.ts deleted file mode 100644 index 64b762793..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/datetime.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, test } from '@nocobase/test/e2e'; -import dayjs from 'dayjs'; -import { commonTesting, testDefaultValue, testPattern } from '../commonTesting'; - -test.describe('datetime', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'datetime', blockType: 'creating', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'datetime'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByPlaceholder('Select date').click(); - await page.getByText('Today').click(); - }, - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toHaveValue(dayjs().format('YYYY-MM-DD')); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'datetime'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date') - .click(); - await page.getByText('Today').click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( - `datetime:${dayjs().format('YYYY-MM-DD')}`, - ); - }, - }); - }); - - test('date display format', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'datetime' }); - await page.getByRole('menuitem', { name: 'Date display format' }).click(); - await page.getByLabel('YYYY/MM/DD').click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 输入一个值,然后验证格式是否正确 - await page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date') - .click(); - await page.getByText('Today').click(); - - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toHaveValue(dayjs().format('YYYY/MM/DD')); - }); -}); -test.describe('time', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'time', blockType: 'creating', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'time'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByPlaceholder('Select time').click(); - await page.getByText('Now').click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), - ).toHaveValue(new RegExp(dayjs().format('HH:mm:'))); // 去掉后面的秒,是因为可能因为延迟导致秒数不一致 - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'time'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.time-time') - .getByPlaceholder('Select time') - .click(); - await page.getByText('Now').click(); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.time-time')).toHaveText( - new RegExp(`time:${dayjs().format('HH:mm:')}`), - ); - }, - }); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/media.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/media.test.ts deleted file mode 100644 index 24085e1e6..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/media.test.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndMediaFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testDefaultValue, testPattern, testSetValidationRules } from '../commonTesting'; - -test.describe('markdown', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'markdown', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'markdown'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - constantValue: 'test markdown', - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).toHaveValue('test markdown'); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.markdown-markdown') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.markdown-markdown') - .getByRole('textbox') - .fill('test markdown pattern'); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown')).toHaveText( - `markdown:test markdown pattern`, - ); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - }); - }); -}); - -test.describe('rich text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'richText', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord }) => { - await testDefaultValue({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'richText'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-CollectionField-general-general.richText').locator('.ql-editor').click(); - await page.keyboard.type('test rich text'); - }, - expectConstantValue: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( - /test rich text/, - ); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'richText'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.richText-richText') - .locator('.ql-editor') - .click(); - await page.keyboard.type('test rich text pattern'); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), - ).toHaveClass(/ql-disabled/); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( - /test rich text pattern/, - ); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - }); - }); -}); - -test.describe('attachment', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'attachment', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - await testPattern({ - page, - gotoPage: () => gotoPage(mockPage), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'attachment'), - expectEditable: async () => { - await expect(page.getByRole('button', { name: 'plus Upload' })).toBeVisible(); - }, - expectReadonly: async () => { - await expect(page.getByRole('button', { name: 'plus Upload' })).not.toBeVisible(); - }, - expectEasyReading: async () => { - await expect(page.getByRole('button', { name: 'plus Upload' })).not.toBeVisible(); - }, - }); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/relation.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/relation.test.ts deleted file mode 100644 index 15ae415e8..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/relation.test.ts +++ /dev/null @@ -1,658 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testDefaultValue, testPattern } from '../commonTesting'; - -test.describe('many to many', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'manyToMany', fieldType: 'relation', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecords }) => { - let recordsOfUser; - await testDefaultValue({ - page, - gotoPage: async () => { - recordsOfUser = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'manyToMany'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page.getByLabel('block-item-VariableInput-').getByTestId('select-object-multiple').click(); - await page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true }).click(); - await page.getByRole('option', { name: String(recordsOfUser[1].id), exact: true }).click(); - await page.getByRole('option', { name: String(recordsOfUser[2].id), exact: true }).click(); - }, - expectConstantValue: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), - ).toHaveText(`manyToMany:${recordsOfUser.map((record) => record.id).join('')}`); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let records; - await testPattern({ - page, - gotoPage: async () => { - records = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'manyToMany'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple') - .click(); - await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); - await page.getByRole('option', { name: String(records[1].id), exact: true }).click(); - await page.getByRole('option', { name: String(records[2].id), exact: true }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple'), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), - ).toHaveText(`manyToMany:${records.map((record) => record.id).join(',')}`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const records = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(records[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple') - .click(); - await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); - await expect(page.getByRole('option')).toHaveCount(1); - }); - - test('set default sorting rules', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); - - // 配置 - await page.getByRole('button', { name: 'Add sort field' }).click(); - await page.getByTestId('select-single').click(); - await page.getByRole('option', { name: 'ID', exact: true }).click(); - await page.getByText('DESC', { exact: true }).click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); - await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID'); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - - // 选择 Record picker - await page.getByRole('option', { name: 'Record picker', exact: true }).click(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-data-picker'), - ).toBeVisible(); - - // 选择 Sub-table - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - await page.getByRole('option', { name: 'Sub-table', exact: true }).click(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByLabel('schema-initializer-AssociationField.SubTable-TableColumnInitializers-users'), - ).toBeVisible(); - - // 选择 Sub-form - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - await page.getByRole('option', { name: 'Sub-form', exact: true }).click(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByLabel('schema-initializer-Grid-FormItemInitializers-users'), - ).toBeVisible(); - - // 选择 Sub-form(Popover) - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - await page.getByRole('option', { name: 'Sub-form(Popover)', exact: true }).click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByRole('img', { name: 'edit' }) - .click(); - await expect(page.getByTestId('popover-CollectionField-general')).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('allow multiple', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('many to one', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'manyToOne', fieldType: 'relation', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecords }) => { - let records; - await testDefaultValue({ - page, - gotoPage: async () => { - records = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(), - showMenu: () => showMenu(page, 'manyToOne'), - supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'], - inputConstantValue: async () => { - await page - .getByLabel('block-item-VariableInput-') - .getByTestId(/select-object/) - .click(); - await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); - await page - .getByLabel('block-item-VariableInput-') - .getByTestId(/select-object/) - .click(); - await page.getByRole('option', { name: String(records[1].id), exact: true }).click(); - await page - .getByLabel('block-item-VariableInput-') - .getByTestId(/select-object/) - .click(); - await page.getByRole('option', { name: String(records[2].id), exact: true }).click(); - }, - expectConstantValue: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/), - ).toHaveText(String(records[2].id)); - }, - }); - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let records; - await testPattern({ - page, - gotoPage: async () => { - records = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'manyToOne'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/) - .click(); - await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne')).toHaveText( - `manyToOne:${String(records[0].id)}`, - ); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const records = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(records[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId('select-object-single') - .click(); - await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); - await expect(page.getByRole('option')).toHaveCount(1); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to many', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'oneToMany', fieldType: 'relation', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName: 'oneToMany' }); - await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - await testPattern({ - page, - gotoPage: async () => { - await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToMany'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple') - .click(); - // 目前的情况下,在 one to many 的字段中,只有 ID 为 1 的数据可以被选中 - await page.getByRole('option', { name: '1', exact: true }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple'), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany')).toHaveText( - `oneToMany:1`, - ); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const records = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(records[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple') - .click(); - // 默认只显示 id 为 1 的数据,因为设置了只过滤 id 为 3 的数据,所以这里的下拉列表应该为空,mock 的数据无法被选中 - await expect(page.getByRole('option')).toHaveCount(0); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('allow multiple', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to one (belongs to)', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'oneToOneBelongsTo', fieldType: 'relation', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName: 'oneToOneBelongsTo' }); - await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let records; - await testPattern({ - page, - gotoPage: async () => { - records = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToOneBelongsTo'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId(/select-object/) - .click(); - await page.getByRole('option', { name: String(records[0].id), exact: true }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo'), - ).toHaveText(`oneToOneBelongsTo:${String(records[0].id)}`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const records = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(records[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId('select-object-single') - .click(); - await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible(); - await expect(page.getByRole('option')).toHaveCount(1); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to one (has one)', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'oneToOneHasOne', fieldType: 'relation', mode: 'options' }); - - test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, mockRecords, fieldName: 'oneToOneHasOne' }); - await expect(page.getByRole('menuitem', { name: 'Set default value' })).not.toBeVisible(); - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let records; - await testPattern({ - page, - gotoPage: async () => { - records = await gotoPage(mockPage, mockRecords); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToOneHasOne'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId(/select-object/) - .click(); - - // 目前的情况下,在 one to one (has one) 的字段中,只有 ID 为 1 的数据可以被选中,mock 的数据无法被选中 - await page.getByRole('option', { name: '1', exact: true }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne'), - ).toHaveText(`oneToOneHasOne:1`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const records = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(records[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId('select-object-single') - .click(); - // 默认只显示 id 为 1 的数据,因为设置了只过滤 id 为 3 的数据,所以这里的下拉列表应该为空 - await expect(page.getByRole('option')).toHaveCount(0); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage, mockRecords) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const recordsOfUser = await mockRecords('users', 3); - await nocoPage.goto(); - - return recordsOfUser; -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecords, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - mockRecords; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/systemInfo.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/systemInfo.test.ts deleted file mode 100644 index 1be859b66..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-creation/systemInfo.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('created at', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'createdAt', fieldType: 'system', mode: 'options' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdAt' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); - }); -}); -test.describe('created by', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'createdBy', fieldType: 'system', mode: 'options' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdBy' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); -test.describe('id', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'id', fieldType: 'system', mode: 'options' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'id' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('table oid', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'tableoid', fieldType: 'system', mode: 'options' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'tableoid' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('last updated at', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'updatedAt', fieldType: 'system', mode: 'options' }); -}); -test.describe('last updated by', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'updatedBy', fieldType: 'system', mode: 'options' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'updatedBy' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByRole('button', { name: 'Add new' }).click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/advanced.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/advanced.test.ts deleted file mode 100644 index b8f5ae883..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/advanced.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('collection', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'collection', blockType: 'editing', mode: 'options' }); -}); -test.describe('JSON', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'JSON', blockType: 'editing', mode: 'options' }); -}); -test.describe('formula', () => { - test('should display correct options', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'formula' }); - await expect(page.getByRole('menuitem', { name: 'Edit field title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Display title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Delete' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('sequence', () => { - test('should display correct options', async ({ page, mockPage, mockRecord, mockRecords }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'sequence' }); - await expect(page.getByRole('menuitem', { name: 'Edit field title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Display title' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Delete' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Pattern' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Edit description' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'required' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields).waitForInit(); - await mockRecord('general'); - await nocoPage.goto(); -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/basic.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/basic.test.ts deleted file mode 100644 index 9eaa12ed9..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/basic.test.ts +++ /dev/null @@ -1,532 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testPattern, testSetValidationRules } from '../commonTesting'; - -test.describe('color', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'color', blockType: 'editing' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'color'), - expectEditable: async () => { - // 默认情况下显示颜色选择框 - await page.getByLabel('color-picker-normal').hover(); - await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).toBeVisible(); - }, - expectReadonly: async () => { - // 只读模式下,不会显示颜色弹窗 - await page.getByLabel('color-picker-normal').hover(); - await expect(page.getByRole('button', { name: 'right Recommended', exact: true })).not.toBeVisible(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('color-picker-read-pretty')).toBeVisible(); - }, - }); - }); -}); - -test.describe('email', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'email', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'email'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).toHaveValue(record.email); - }, - expectReadonly: async () => { - // 输入框应该被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框应该消失,直接显示值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.email-email').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.email-email')).toHaveText( - `email:${record.email}`, - ); - }, - }); - }); -}); - -test.describe('icon', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'icon', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'icon'), - expectEditable: async () => { - // 默认情况下可以编辑图标 - await page.getByRole('button', { name: 'Select icon' }).click(); - await page.getByLabel('account-book').locator('svg').click(); - }, - expectReadonly: async () => { - // 只读模式下,选择图标按钮会被禁用 - await expect(page.getByRole('button', { name: 'account-book' })).toBeDisabled(); - }, - expectEasyReading: async () => { - // 按钮会消失,只剩下图标 - await expect(page.getByRole('button', { name: 'account-book' })).not.toBeVisible(); - }, - }); - }); -}); - -test.describe('single line text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleLineText', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleLineText'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).toHaveValue(record.singleLineText); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText') - .getByRole('textbox'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText'), - ).toHaveText(`singleLineText:${record.singleLineText}`); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleLineText'), - }); - }); -}); - -test.describe('integer', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'integer', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'integer'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).toHaveValue(String(record.integer)); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText( - `integer:${record.integer}`, - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'integer'), - }); - }); -}); - -test.describe('number', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'number', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - // TODO: number 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数不应该被去掉; - test.fail(); - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'number'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).toHaveValue(String(record.number)); - - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.number-number') - .getByRole('spinbutton') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.number-number') - .getByRole('spinbutton') - .fill('11.22'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.number-number').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.number-number')).toHaveText( - 'number:11.22', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'number'), - }); - }); -}); - -test.describe('password', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'password', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'password'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.password-password') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.password-password') - .getByRole('textbox') - .fill('test112233password'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.password-password')).toHaveText( - 'password:********', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'password'), - }); - }); -}); - -test.describe('percent', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'percent', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - // TODO: percent 类型的字段,当输入了小数,然后把 Pattern 切换成 Easy-reading 模式,小数点不应该被去掉; - test.fail(); - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'percent'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).toHaveValue(String(record.percent)); - - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.percent-percent') - .getByRole('spinbutton') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.percent-percent') - .getByRole('spinbutton') - .fill('11.22'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.percent-percent').getByRole('spinbutton'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.percent-percent')).toHaveText( - 'percent:11.22%', - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'percent'), - }); - }); -}); - -test.describe('phone', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'phone', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'phone'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.phone-phone') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.phone-phone') - .getByRole('textbox') - .fill('17777777777'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // 输入框会消失,只剩下值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone-phone')).toHaveText( - 'phone:17777777777', - ); - }, - }); - }); -}); - -test.describe('long text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'longText', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'longText'), - expectEditable: async () => { - // 应该显示 record 中的值 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).toHaveValue(record.longText); - - // 默认情况下可以编辑 - await page - .getByLabel('block-item-CollectionField-general-form-general.longText-longText') - .getByRole('textbox') - .click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.longText-longText') - .getByRole('textbox') - .fill('test long text'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.longText-longText')).toHaveText( - `longText:test long text`, - ); - }, - }); - }); - - test('set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'longText'), - }); - }); -}); - -test.describe('URL', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'url', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'url'), - expectEditable: async () => { - // 默认情况下可以编辑 - await page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox').click(); - await page - .getByLabel('block-item-CollectionField-general-form-general.url-url') - .getByRole('textbox') - .fill('https://nocobase.com'); - }, - expectReadonly: async () => { - // 只读模式下,输入框会被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText( - 'url:https://nocobase.com', - ); - }, - }); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/choices.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/choices.test.ts deleted file mode 100644 index c2c69ec56..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/choices.test.ts +++ /dev/null @@ -1,289 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testPattern } from '../commonTesting'; - -test.describe('checkbox', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkbox', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'checkbox'), - expectEditable: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).toBeChecked({ checked: record.checkbox }); - }, - expectReadonly: async () => { - // checkbox 应该被禁用 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // checkbox 应该被隐藏,然后只显示一个图标 - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox').getByRole('checkbox'), - ).not.toBeVisible(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkbox-checkbox') - .getByRole('img', { name: 'check' }), - ).toBeVisible({ visible: record.checkbox }); - }, - }); - }); -}); - -test.describe('checkbox group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'checkboxGroup', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'checkboxGroup'), - expectEditable: async () => { - for (const option of record.checkboxGroup) { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: option }), - ).toBeChecked(); - } - }, - expectReadonly: async () => { - // checkbox 应该被禁用 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - // checkbox 应该被隐藏,然后只显示标签 - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup') - .getByRole('checkbox', { name: 'Option1' }), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.checkboxGroup-checkboxGroup'), - ).toHaveText(`checkboxGroup:${record.checkboxGroup.join('')}`, { ignoreCase: true }); - }, - }); - }); -}); - -test.describe('china region', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'chinaRegion', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'chinaRegion'), - expectEditable: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .click(); - await page.getByRole('menuitemcheckbox', { name: '北京市' }).click(); - await page.getByRole('menuitemcheckbox', { name: '市辖区' }).click(); - await page.getByRole('menuitemcheckbox', { name: '东城区' }).click(); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .getByRole('combobox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion') - .locator('.ant-select') - .getByRole('combobox'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.chinaRegion-chinaRegion'), - ).toHaveText('chinaRegion:北京市 / 市辖区 / 东城区'); - }, - }); - }); -}); - -test.describe('multiple select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'multipleSelect', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'multipleSelect'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple'), - ).toHaveText(`${record.multipleSelect.join('')}`, { ignoreCase: true }); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple'), - ).toHaveClass(/ant-select-disabled/); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect') - .getByTestId('select-multiple'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.multipleSelect-multipleSelect'), - ).toHaveText(`multipleSelect:${record.multipleSelect.join('')}`, { ignoreCase: true }); - }, - }); - }); -}); - -test.describe('radio group', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'radioGroup', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'radioGroup'), - expectEditable: async () => { - if (record.radioGroup) { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel(record.radioGroup), - ).toBeChecked(); - } - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup') - .getByLabel('Option2'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.radioGroup-radioGroup'), - ).toHaveText(`radioGroup:${record.radioGroup}`, { ignoreCase: true }); - }, - }); - }); -}); - -test.describe('single select', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'singleSelect', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'singleSelect'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single'), - ).toHaveText(record.singleSelect, { ignoreCase: true }); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single'), - ).toHaveClass(/ant-select-disabled/); - }, - expectEasyReading: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect') - .getByTestId('select-single'), - ).not.toBeVisible(); - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.singleSelect-singleSelect'), - ).toHaveText(`singleSelect:${record.singleSelect}`, { ignoreCase: true }); - }, - }); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndChoicesFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/datetime.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/datetime.test.ts deleted file mode 100644 index 51aa8694c..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/datetime.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, test } from '@nocobase/test/e2e'; -import dayjs from 'dayjs'; -import { commonTesting, testPattern } from '../commonTesting'; - -test.describe('datetime', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'datetime', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'datetime'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toHaveValue(dayjs(record.datetime).format('YYYY-MM-DD')); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.datetime-datetime')).toHaveText( - `datetime:${dayjs(record.datetime).format('YYYY-MM-DD')}`, - ); - }, - }); - }); - - test('date display format', async ({ page, mockPage, mockRecord }) => { - const record = await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'datetime' }); - await page.getByRole('menuitem', { name: 'Date display format' }).click(); - await page.getByLabel('YYYY/MM/DD').click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.datetime-datetime') - .getByPlaceholder('Select date'), - ).toHaveValue(dayjs(record.datetime).format('YYYY/MM/DD')); - }); -}); - -test.describe('time', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'time', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'time'), - expectEditable: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), - ).toHaveValue(record.time); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.time-time')).toHaveText( - new RegExp(`time:${record.time}`), - ); - }, - }); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - const record = await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); - - return record; -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/media.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/media.test.ts deleted file mode 100644 index 26768b17f..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/media.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndMediaFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testPattern, testSetValidationRules } from '../commonTesting'; - -test.describe('markdown', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'markdown', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - expectEditable: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).toHaveValue(record.markdown); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).toBeDisabled(); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown')).toHaveText( - `markdown:${record.markdown}`, - ); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - }); - }); -}); - -test.describe('rich text', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'richText', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'richText'), - expectEditable: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-editor'), - ).toHaveText(record.richText); - }, - expectReadonly: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), - ).toHaveClass(/ql-disabled/); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-container'), - ).not.toBeVisible(); - await expect(page.getByLabel('block-item-CollectionField-general-form-general.richText-richText')).toHaveText( - `richText:${record.richText}`, - ); - }, - }); - }); - - test('Set validation rules', async ({ page, mockPage, mockRecord }) => { - await testSetValidationRules({ - page, - gotoPage: () => gotoPage(mockPage, mockRecord), - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'markdown'), - }); - }); -}); - -test.describe('attachment', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'attachment', blockType: 'editing', mode: 'options' }); - - test('pattern', async ({ page, mockPage, mockRecord }) => { - let record = null; - await testPattern({ - page, - gotoPage: async () => { - record = await gotoPage(mockPage, mockRecord); - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'attachment'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first(), - ).toBeVisible(); - }, - expectReadonly: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first() - .hover(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('button', { name: 'delete' }), - ).not.toBeVisible(); - }, - expectEasyReading: async () => { - await page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('link', { name: record.attachment.title }) - .first() - .hover(); - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.attachment-attachment') - .getByRole('button', { name: 'delete' }), - ).not.toBeVisible(); - }, - }); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page - .getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true }) - .hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, { - exact: true, - }) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/relation.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/relation.test.ts deleted file mode 100644 index 6b768a23a..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/relation.test.ts +++ /dev/null @@ -1,567 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test } from '@nocobase/test/e2e'; -import { commonTesting, testPattern } from '../commonTesting'; - -test.describe('many to many', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'manyToMany', - fieldType: 'relation', - mode: 'options', - blockType: 'editing', - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let record; - await testPattern({ - page, - gotoPage: async () => { - record = (await gotoPage(mockPage, mockRecords)).record; - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'manyToMany'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple'), - ).toHaveText(`${record.manyToMany.map((item) => item.id).join('')}`); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple'), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'), - ).toHaveText(`manyToMany:${record.manyToMany.map((item) => item.id).join(',')}`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const { recordsOfUser } = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany') - .getByTestId('select-object-multiple') - .click(); - await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); - }); - - test('set default sorting rules', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); - - // 配置 - await page.getByRole('button', { name: 'Add sort field' }).click(); - await page.getByTestId('select-single').click(); - await page.getByRole('option', { name: 'ID', exact: true }).click(); - await page.getByText('DESC', { exact: true }).click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Set default sorting rules' }).click(); - await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID'); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('allow multiple', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('many to one', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'manyToOne', - fieldType: 'relation', - mode: 'options', - blockType: 'editing', - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let record; - await testPattern({ - page, - gotoPage: async () => { - record = (await gotoPage(mockPage, mockRecords)).record; - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'manyToOne'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/), - ).toHaveText(`${record.manyToOne.id}`); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne')).toHaveText( - `manyToOne:${record.manyToOne.id}`, - ); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const { recordsOfUser } = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.manyToOne-manyToOne') - .getByTestId(/select-object/) - .click(); - await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); - await expect(page.getByRole('option')).toHaveCount(2); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'manyToOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to many', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToMany', - fieldType: 'relation', - mode: 'options', - blockType: 'editing', - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let record; - await testPattern({ - page, - gotoPage: async () => { - record = (await gotoPage(mockPage, mockRecords)).record; - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToMany'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple'), - ).toHaveText(`${record.oneToMany.map((item) => item.id).join('')}`); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple'), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany')).toHaveText( - `oneToMany:${record.oneToMany.map((item) => item.id).join(',')}`, - ); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const { record } = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill('1'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue('1'); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany') - .getByTestId('select-object-multiple') - .click(); - // 但是在编辑模式下,本身已经有数据,所以需要加上已有数据的个数 - await expect(page.getByRole('option')).toHaveCount(1 + record.oneToMany.length); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('allow multiple', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToMany'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to one (belongs to)', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToOneBelongsTo', - fieldType: 'relation', - mode: 'options', - blockType: 'editing', - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let record; - await testPattern({ - page, - gotoPage: async () => { - record = (await gotoPage(mockPage, mockRecords)).record; - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToOneBelongsTo'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId(/select-object/), - ).toHaveText(`${record.oneToOneBelongsTo.id}`); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo'), - ).toHaveText(`oneToOneBelongsTo:${record.oneToOneBelongsTo.id}`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - const { recordsOfUser } = await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id)); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo') - .getByTestId(/select-object/) - .click(); - await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible(); - await expect(page.getByRole('option')).toHaveCount(2); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneBelongsTo'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -test.describe('one to one (has one)', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'oneToOneHasOne', - fieldType: 'relation', - mode: 'options', - blockType: 'editing', - }); - - test('pattern', async ({ page, mockPage, mockRecords }) => { - let record; - await testPattern({ - page, - gotoPage: async () => { - record = (await gotoPage(mockPage, mockRecords)).record; - }, - openDialog: () => openDialog(page), - showMenu: () => showMenu(page, 'oneToOneHasOne'), - expectEditable: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId(/select-object/), - ).toHaveText(`${record.oneToOneHasOne.id}`); - }, - expectReadonly: async () => { - await expect( - page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId(/select-object/), - ).toHaveClass(/ant-select-disabled/); - // 在这里等待一下,防止因闪烁导致下面的断言失败 - await page.waitForTimeout(100); - }, - expectEasyReading: async () => { - await expect( - page.getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne'), - ).toHaveText(`oneToOneHasOne:${record.oneToOneHasOne.id}`); - }, - }); - }); - - test('Set the data scope', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await page.getByText('Add condition', { exact: true }).click(); - await page.getByTestId('select-filter-field').click(); - await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click(); - await page.getByRole('spinbutton').click(); - await page.getByRole('spinbutton').fill('1'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 再次打开弹窗,设置的值应该还在 - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Set the data scope' }).click(); - await expect(page.getByTestId('select-filter-field')).toHaveText('ID'); - await expect(page.getByRole('spinbutton')).toHaveValue('1'); - await page.getByRole('button', { name: 'Cancel', exact: true }).click(); - - // 数据应该被过滤了 - await page - .getByLabel('block-item-CollectionField-general-form-general.oneToOneHasOne-oneToOneHasOne') - .getByTestId(/select-object/) - .click(); - await expect(page.getByRole('option')).toHaveCount(2); - }); - - test('field component', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await page.getByRole('menuitem', { name: 'Field component' }).click(); - - // 断言支持的选项 - await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible(); - await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible(); - }); - - test('quick create', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - - await expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecords }) => { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, 'oneToOneHasOne'); - await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage, mockRecords) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const recordsOfUser = await mockRecords('users', 3); - const record = (await mockRecords('general', 1))[0]; - await nocoPage.goto(); - - return { record, recordsOfUser }; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecords, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - mockRecords; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecords); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/systemInfo.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/systemInfo.test.ts deleted file mode 100644 index ab02b60bd..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/form-item/form-edit/systemInfo.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Page, expect, oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, test } from '@nocobase/test/e2e'; -import { commonTesting } from '../commonTesting'; - -test.describe('created at', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'createdAt', - fieldType: 'system', - mode: 'options', - blockType: 'editing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdAt' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Date display format' })).toBeVisible(); - }); -}); -test.describe('created by', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'createdBy', - fieldType: 'system', - mode: 'options', - blockType: 'editing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'createdBy' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); -test.describe('id', () => { - commonTesting({ openDialogAndShowMenu, fieldName: 'id', fieldType: 'system', mode: 'options', blockType: 'editing' }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'id' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('table oid', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'tableoid', - fieldType: 'system', - mode: 'options', - blockType: 'editing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'tableoid' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - }); -}); -test.describe('last updated at', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'updatedAt', - fieldType: 'system', - mode: 'options', - blockType: 'editing', - }); -}); -test.describe('last updated by', () => { - commonTesting({ - openDialogAndShowMenu, - fieldName: 'updatedBy', - fieldType: 'system', - mode: 'options', - blockType: 'editing', - }); - - test('options', async ({ page, mockPage, mockRecord }) => { - await openDialogAndShowMenu({ page, mockPage, mockRecord, fieldName: 'updatedBy' }); - await expect(page.getByRole('menuitem', { name: 'Edit tooltip' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Enable link' })).toBeVisible(); - }); -}); - -const gotoPage = async (mockPage, mockRecord) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - return record; -}; - -const openDialog = async (page: Page) => { - await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click(); -}; - -const showMenu = async (page: Page, fieldName: string) => { - await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-`).hover(); - await page - .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`) - .hover(); -}; - -async function openDialogAndShowMenu({ - page, - mockPage, - mockRecord, - fieldName, -}: { - page: Page; - mockPage; - mockRecord; - fieldName: string; -}) { - await gotoPage(mockPage, mockRecord); - await openDialog(page); - await showMenu(page, fieldName); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/advanced.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/advanced.test.ts deleted file mode 100644 index 6e84c4734..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/advanced.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, test } from '@nocobase/test/e2e'; -import { testSupportedOptions } from './utils'; - -test.describe('collection', () => { - testSupportedOptions({ - name: 'collection', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, - }); -}); - -test.describe('JSON', () => { - testSupportedOptions({ - name: 'JSON', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, - }); -}); - -test.describe('formula', () => { - testSupportedOptions({ - name: 'formula', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, - }); -}); - -test.describe('sequence', () => { - testSupportedOptions({ - name: 'sequence', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAdvancedFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/basic.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/basic.test.ts deleted file mode 100644 index 3ba574e16..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/basic.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { expect, oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test } from '@nocobase/test/e2e'; -import { createColumnItem, showSettingsMenu, testSupportedOptions } from './utils'; - -test.describe('single line text', () => { - testSupportedOptions({ - name: 'singleLineText', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); - - test('custom column title', async ({ page, mockPage, mockRecords }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - await mockRecords('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'singleLineText'); - await showSettingsMenu(page, 'singleLineText'); - await page.getByRole('menuitem', { name: 'Custom column title' }).click(); - - // 显示出原字段名称 - await expect(page.getByRole('dialog').getByText('Original field title: singleLineText')).toBeVisible(); - // 输入新字段名称 - await page.getByLabel('block-item-Input-general-column title').getByRole('textbox').click(); - await page.getByLabel('block-item-Input-general-column title').getByRole('textbox').fill('new column title'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - // 新名称应该显示出来 - await expect(page.getByRole('button', { name: 'new column title', exact: true })).toBeVisible(); - }); - - test('column width', async ({ page, mockPage, mockRecords }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - await mockRecords('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'singleLineText'); - await showSettingsMenu(page, 'singleLineText'); - await page.getByRole('menuitem', { name: 'Column width' }).click(); - await page.getByRole('dialog').getByRole('spinbutton').click(); - await page.getByRole('dialog').getByRole('spinbutton').fill('600'); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - - const columnHeadSize = await page.getByRole('columnheader', { name: 'singleLineText' }).boundingBox(); - expect(Math.floor(columnHeadSize.width)).toBe(600); - }); - - test('sortable', async ({ page, mockPage, mockRecords }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - await mockRecords('general', [{ singleLineText: 'a' }, { singleLineText: 'b' }]); - await nocoPage.goto(); - - await createColumnItem(page, 'singleLineText'); - await showSettingsMenu(page, 'singleLineText'); - - // 默认不可排序 - await expect(page.getByRole('menuitem', { name: 'Sortable' }).getByRole('switch')).not.toBeChecked(); - - // 开启排序 - await page.getByRole('menuitem', { name: 'Sortable' }).click(); - // TODO: 此处菜单在点击后不应该消失 - // await expect(page.getByRole('menuitem', { name: 'Sortable' }).getByRole('switch')).toBeChecked(); - - // 鼠标 hover 时,有提示 - await page.getByRole('columnheader', { name: 'singleLineText' }).hover(); - await expect(page.getByRole('tooltip', { name: 'Click to sort ascending' })).toBeVisible(); - - // 点击第一下,升序 - await page.getByRole('columnheader', { name: 'singleLineText' }).click(); - let sizeA = await page.getByRole('cell', { name: 'a', exact: true }).boundingBox(); - let sizeB = await page.getByRole('cell', { name: 'b', exact: true }).boundingBox(); - expect(sizeA.y).toBeLessThan(sizeB.y); - - // 点击第二下,降序 - await page.getByRole('columnheader', { name: 'singleLineText' }).click(); - sizeA = await page.getByRole('cell', { name: 'a', exact: true }).boundingBox(); - sizeB = await page.getByRole('cell', { name: 'b', exact: true }).boundingBox(); - expect(sizeA.y).toBeGreaterThan(sizeB.y); - }); - - test('delete', async ({ page, mockPage, mockRecords }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).waitForInit(); - await mockRecords('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'singleLineText'); - await showSettingsMenu(page, 'singleLineText'); - await page.getByRole('menuitem', { name: 'Delete' }).click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - await expect(page.getByRole('columnheader', { name: 'singleLineText' })).toBeHidden(); - }); -}); - -test.describe('color', () => { - testSupportedOptions({ - name: 'color', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('email', () => { - testSupportedOptions({ - name: 'email', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('icon', () => { - testSupportedOptions({ - name: 'icon', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('integer', () => { - testSupportedOptions({ - name: 'integer', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('number', () => { - testSupportedOptions({ - name: 'number', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('password', () => { - testSupportedOptions({ - name: 'password', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('percent', () => { - testSupportedOptions({ - name: 'percent', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('phone', () => { - testSupportedOptions({ - name: 'phone', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('long text', () => { - testSupportedOptions({ - name: 'longText', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); - -test.describe('url', () => { - testSupportedOptions({ - name: 'url', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndBasicFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/choices.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/choices.test.ts deleted file mode 100644 index cfb8bb1da..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/choices.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, test } from '@nocobase/test/e2e'; -import { testSupportedOptions } from './utils'; - -test.describe('checkbox', () => { - testSupportedOptions({ - name: 'checkbox', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); - -test.describe('checkbox group', () => { - testSupportedOptions({ - name: 'checkboxGroup', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); - -test.describe('china region', () => { - testSupportedOptions({ - name: 'chinaRegion', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); - -test.describe('multiple select', () => { - testSupportedOptions({ - name: 'multipleSelect', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); - -test.describe('radio group', () => { - testSupportedOptions({ - name: 'radioGroup', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); - -test.describe('single select', () => { - testSupportedOptions({ - name: 'singleSelect', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndChoicesFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/datetime.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/datetime.test.ts deleted file mode 100644 index 07c2e3f8a..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/datetime.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { expect, oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, test } from '@nocobase/test/e2e'; -import dayjs from 'dayjs'; -import { createColumnItem, showSettingsMenu, testSupportedOptions } from './utils'; - -test.describe('datetime', () => { - testSupportedOptions({ - name: 'datetime', - options: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, - }); - - test('date display format', async ({ page, mockPage, mockRecords }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields).waitForInit(); - const records = await mockRecords('general', 1); - await nocoPage.goto(); - - await createColumnItem(page, 'datetime'); - await showSettingsMenu(page, 'datetime'); - await page.getByRole('menuitem', { name: 'Date display format' }).click(); - await page.getByLabel('MM/DD/YY').click(); - await page.getByRole('button', { name: 'OK', exact: true }).click(); - await expect( - page.getByRole('cell', { name: dayjs(records[0].datetime).format('MM/DD/YY'), exact: true }), - ).toBeVisible(); - }); -}); - -test.describe('time', () => { - testSupportedOptions({ - name: 'time', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndDatetimeFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/media.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/media.test.ts deleted file mode 100644 index dd26f81b6..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/media.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { oneTableBlockWithAddNewAndViewAndEditAndMediaFields, test } from '@nocobase/test/e2e'; -import { testSupportedOptions } from './utils'; - -test.describe('markdown', () => { - testSupportedOptions({ - name: 'markdown', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndMediaFields, - }); -}); - -test.describe('rich text', () => { - testSupportedOptions({ - name: 'richText', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndMediaFields, - }); -}); - -test.describe('attachment', () => { - testSupportedOptions({ - name: 'attachment', - options: ['Custom column title', 'Column width', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndMediaFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/relation.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/relation.test.ts deleted file mode 100644 index 4e6f1fb74..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/relation.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { expect, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test } from '@nocobase/test/e2e'; -import { createColumnItem, showSettingsMenu, testSupportedOptions } from './utils'; - -test.describe('many to one', () => { - testSupportedOptions({ - name: 'manyToOne', - options: ['Custom column title', 'Column width', 'Enable link', 'Title field', 'Field component', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, - }); - - test('enable link', async ({ page, mockPage, mockRecord }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'manyToOne'); - await showSettingsMenu(page, 'manyToOne'); - - // 默认开启 enable link - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeVisible(); - - // 关闭 enable link - await page.getByRole('menuitem', { name: 'Enable link' }).click(); - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked(); - await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeHidden(); - - // 再次开启 - await page.getByRole('menuitem', { name: 'Enable link' }).click(); - await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked(); - await expect(page.locator('a').filter({ has: page.getByText(record.manyToOne.id, { exact: true }) })).toBeVisible(); - }); - - test('title field', async ({ page, mockPage, mockRecord }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'manyToOne'); - await showSettingsMenu(page, 'manyToOne'); - - // 默认是 ID - await expect(page.getByRole('menuitem', { name: 'Title field' })).toHaveText('Title fieldID'); - await expect(page.getByRole('cell', { name: record.manyToOne.id, exact: true })).toBeVisible(); - - // 修改为 nickname - await page.getByRole('menuitem', { name: 'Title field' }).click(); - await page.getByRole('option', { name: 'Nickname' }).click(); - await page.mouse.move(300, 0); - await expect(page.getByRole('cell', { name: record.manyToOne.nickname, exact: true })).toBeVisible(); - }); - - test('field component', async ({ page, mockPage, mockRecord }) => { - const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); - const record = await mockRecord('general'); - await nocoPage.goto(); - - await createColumnItem(page, 'manyToOne'); - await showSettingsMenu(page, 'manyToOne'); - - // 默认是 Title - await expect(page.getByRole('menuitem', { name: 'Field component' })).toHaveText('Field componentTitle'); - - // 修改为 Tag - await page.getByRole('menuitem', { name: 'Field component' }).click(); - await page.getByRole('option', { name: 'Tag' }).click(); - // 修改成功之后会显示 Tag color field 选项 - await expect(page.getByRole('menuitem', { name: 'Tag color field' })).toBeVisible(); - await expect( - page.getByRole('cell', { name: record.manyToOne.id, exact: true }).filter({ has: page.locator('.ant-tag') }), - ).toBeVisible(); - }); -}); - -test.describe('many to many', () => { - testSupportedOptions({ - name: 'manyToMany', - options: ['Custom column title', 'Column width', 'Enable link', 'Title field', 'Field component', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, - }); -}); - -test.describe('one to many', () => { - testSupportedOptions({ - name: 'oneToMany', - options: ['Custom column title', 'Column width', 'Enable link', 'Title field', 'Field component', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, - }); -}); - -test.describe('one to one (belongs to)', () => { - testSupportedOptions({ - name: 'oneToOneBelongsTo', - options: ['Custom column title', 'Column width', 'Enable link', 'Title field', 'Field component', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, - }); -}); - -test.describe('one to one (has one)', () => { - testSupportedOptions({ - name: 'oneToOneHasOne', - options: ['Custom column title', 'Column width', 'Enable link', 'Title field', 'Field component', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/systemInfo.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/systemInfo.test.ts deleted file mode 100644 index 1248e3bbb..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/systemInfo.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, test } from '@nocobase/test/e2e'; -import { testSupportedOptions } from './utils'; - -test.describe('created at', () => { - testSupportedOptions({ - name: 'Created at', - options: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); - -test.describe('created by', () => { - testSupportedOptions({ - name: 'Created by', - options: ['Custom column title', 'Column width', 'Enable link', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); - -test.describe('id', () => { - testSupportedOptions({ - name: 'ID', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); - -test.describe('table oid', () => { - testSupportedOptions({ - name: 'Table OID', - options: ['Custom column title', 'Column width', 'Sortable', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); - -test.describe('last updated at', () => { - testSupportedOptions({ - name: 'Last updated at', - options: ['Custom column title', 'Column width', 'Sortable', 'Date display format', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); - -test.describe('last updated by', () => { - testSupportedOptions({ - name: 'Last updated by', - options: ['Custom column title', 'Column width', 'Enable link', 'Delete'], - template: oneTableBlockWithAddNewAndViewAndEditAndSystemInfoFields, - }); -}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/utils.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/utils.ts deleted file mode 100644 index 76a05efd0..000000000 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/schema-settings/table-column-item/utils.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Page, PageConfig, expectSettingsMenu, test } from '@nocobase/test/e2e'; - -export function testSupportedOptions({ - name, - options, - template, -}: { - name: string; - options: string[]; - template: PageConfig; -}) { - test('supported options', async ({ page, mockPage, mockRecord }) => { - const nocoPage = await mockPage(template).waitForInit(); - await mockRecord('general'); - await nocoPage.goto(); - - await expectSettingsMenu({ - page, - showMenu: async () => { - await createColumnItem(page, name); - await showSettingsMenu(page, name); - }, - supportedOptions: options, - }); - }); -} - -export async function showSettingsMenu(page: Page, fieldName: string) { - await page.getByRole('columnheader', { name: fieldName, exact: true }).hover(); - await page.getByLabel('designer-schema-settings-TableV2.Column-TableV2.Column.Designer-').hover(); -} - -export async function createColumnItem(page: Page, fieldName: string) { - await page.getByLabel('schema-initializer-TableV2-TableColumnInitializers-general').hover(); - await page.getByRole('menuitem', { name: fieldName, exact: true }).click(); - await page.mouse.move(300, 0); -} diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/utils.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/utils.ts new file mode 100644 index 000000000..1f804e15f --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/utils.ts @@ -0,0 +1,506 @@ +import { Page, expect } from '@nocobase/test/e2e'; + +export async function showSettingsMenu(page: Page, fieldName: string) { + await page.getByRole('columnheader', { name: fieldName, exact: true }).hover(); + await page.getByLabel('designer-schema-settings-TableV2.Column-TableV2.Column.Designer-').hover(); +} + +export async function createColumnItem(page: Page, fieldName: string) { + await page.getByLabel('schema-initializer-TableV2-TableColumnInitializers-general').hover(); + await page.getByRole('menuitem', { name: fieldName, exact: true }).click(); + await page.mouse.move(300, 0); +} + +export async function testEditFieldTitle(page: Page) { + await page.getByRole('menuitem', { name: 'Edit field title' }).click(); + await page.getByLabel('block-item-Input-general-').getByRole('textbox').click(); + await page.getByLabel('block-item-Input-general-').getByRole('textbox').fill('testing edit field title'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await expect(page.getByText('testing edit field title')).toBeVisible(); +} + +export async function testDisplayTitle(page: Page, title: string) { + // 默认情况下是开启状态 + await expect(page.getByRole('menuitem', { name: 'Display title' }).getByRole('switch')).toBeChecked(); + await page.getByRole('menuitem', { name: 'Display title' }).click(); + await expect(page.getByRole('menuitem', { name: 'Display title' }).getByRole('switch')).not.toBeChecked(); + await expect(page.getByText(`${title}:`, { exact: true })).not.toBeVisible(); +} + +export async function testEditDescription(page: Page) { + await page.getByRole('menuitem', { name: 'Edit description' }).click(); + await page.getByLabel('block-item-Input.TextArea-').getByRole('textbox').click(); + await page.getByLabel('block-item-Input.TextArea-').getByRole('textbox').fill('testing edit description'); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await expect(page.getByText('testing edit description')).toBeVisible(); +} + +export async function testRequired(page: Page) { + // 默认情况下是关闭状态 + await expect(page.getByRole('menuitem', { name: 'Required' }).getByRole('switch')).not.toBeChecked(); + await page.getByRole('menuitem', { name: 'Required' }).click(); + await expect(page.getByRole('menuitem', { name: 'Required' }).getByRole('switch')).toBeChecked(); +} + +export async function clickDeleteAndOk(page: Page) { + await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); +} + +export async function testDefaultValue({ + page, + openDialog, + closeDialog, + gotoPage, + showMenu, + supportVariables, + constantValue, + variableValue, + inputConstantValue, + expectConstantValue, + expectVariableValue, +}: { + page: Page; + openDialog: () => Promise; + closeDialog: () => Promise; + gotoPage: () => Promise; + showMenu: () => Promise; + /** 支持的变量列表,如:['Current user', 'Date variables', 'Current form'] */ + supportVariables: string[]; + /** 常量默认值 */ + constantValue?: string | number; + /** 变量默认值 */ + variableValue?: string[]; + /** 输入常量默认值 */ + inputConstantValue?: () => Promise; + /** 对常量默认值进行断言 */ + expectConstantValue?: () => Promise; + /** 对变量默认值进行断言 */ + expectVariableValue?: () => Promise; +}) { + await gotoPage(); + await openDialog(); + await showMenu(); + + if (constantValue || inputConstantValue) { + // 设置一个常量作为默认值 + await page.getByRole('menuitem', { name: 'Set default value' }).click(); + if (inputConstantValue) { + await inputConstantValue(); + } else { + await page.getByLabel('block-item-VariableInput-').getByRole('textbox').click(); + await page.getByLabel('block-item-VariableInput-').getByRole('textbox').fill(String(constantValue)); + } + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 关闭弹窗,然后再次打开后,应该显示刚才设置的默认值 + await closeDialog(); + await openDialog(); + await expectConstantValue?.(); + } + + if (variableValue) { + // 设置一个变量作为默认值 + await showMenu(); + await page.getByRole('menuitem', { name: 'Set default value' }).click(); + await page.getByLabel('variable-button').click(); + for (const value of supportVariables) { + await expect(page.getByRole('menuitemcheckbox', { name: value })).toBeVisible(); + } + for (const value of variableValue) { + await page.getByRole('menuitemcheckbox', { name: value }).click(); + } + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await closeDialog(); + await openDialog(); + await expectVariableValue?.(); + } +} + +export async function testPattern({ + page, + gotoPage, + openDialog, + showMenu, + expectEditable, + expectReadonly, + expectEasyReading, +}: { + page: Page; + gotoPage: () => Promise; + openDialog: () => Promise; + showMenu: () => Promise; + /** 断言选项为 Editable 的情况 */ + expectEditable: () => Promise; + /** 断言选项为 Readonly 的情况 */ + expectReadonly: () => Promise; + /** 断言选项为 Easy-reading 的情况 */ + expectEasyReading: () => Promise; +}) { + await gotoPage(); + await openDialog(); + + // 默认情况下,显示的是 Editable + await expectEditable(); + await showMenu(); + await expect(page.getByText('PatternEditable')).toBeVisible(); + + // 更改为 Readonly + await page.getByRole('menuitem', { name: 'Pattern' }).click(); + await page.getByRole('option', { name: 'Readonly' }).click(); + await expectReadonly(); + + // 更改为 Easy-reading + await showMenu(); + await expect(page.getByText('PatternReadonly')).toBeVisible(); + await page.getByRole('menuitem', { name: 'Pattern' }).click(); + await page.getByRole('option', { name: 'Easy-reading' }).click(); + await expectEasyReading(); + + await showMenu(); + await expect(page.getByText('PatternEasy-reading')).toBeVisible(); +} + +export async function testSetValidationRules({ + page, + gotoPage, + openDialog, + showMenu, +}: { + page: Page; + gotoPage: () => Promise; + openDialog: () => Promise; + showMenu: () => Promise; +}) { + await gotoPage(); + await openDialog(); + await showMenu(); + + await page.getByRole('menuitem', { name: 'Set validation rules' }).click(); + await expect(page.getByRole('dialog').getByText('Set validation rules')).toBeVisible(); + + // TODO: 更详细的测试 +} + +export class CollectionManagerPage { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + async goto() { + await this.page.goto('admin/settings/collection-manager/collections'); + } + + async createCollection( + template: + | 'General collection' + | 'Calendar collection' + | 'Tree collection' + | 'Expression collection' + | 'SQL collection' + | 'File collection' + | 'Connect to database view', + ) { + await this.page.getByRole('button', { name: 'Create collection' }).hover(); + await this.page.getByRole('menuitem', { name: template }).click(); + return new CollectionSettings(this.page); + } + + /** + * 对应页面中每行数据表的 Configure fields 按钮 + * @param collectionName 数据表字段标识 + * @returns + */ + async configureFields(collectionName: string) { + await this.page.getByLabel(`action-Action.Link-Configure fields-collections-${collectionName}`).click(); + return new FieldsSettings(this.page); + } + + /** + * 对应页面中每行数据表的 Edit 按钮 + * @param collectionName 数据表字段标识 + * @returns + */ + async edit(collectionName: string) { + await this.page.getByLabel(`edit-button-${collectionName}`).click(); + return new CollectionSettings(this.page); + } + + /** + * 对应页面中每行数据表的 Delete 按钮 + * @param collectionName 数据表字段标识 + */ + async deleteItem(collectionName: string) { + await this.page.getByLabel(`delete-button-${collectionName}`).click(); + await this.page.getByLabel('action-Action-Ok-collections-').click(); + } + + async addCategory(name: string, color?: 'Red' | 'Green' | 'Blue') { + await this.page.getByRole('button', { name: 'Add tab' }).click(); + await this.page.getByLabel('block-item-Input-collections-').getByRole('textbox').fill(name); + if (color) { + await this.page.getByLabel('block-item-ColorSelect-').locator('.ant-select-selector').click(); + await this.page.getByRole('option', { name: color, exact: true }).click(); + } + await this.page.getByLabel('action-Action-Submit-').click(); + } + + async deleteCategory(name: string) { + await this.page.getByLabel(name).hover(); + await this.page.getByRole('menuitem', { name: 'Delete category' }).click(); + await this.page.getByRole('button', { name: 'OK', exact: true }).click(); + } +} + +/** + * 用来配置 Collection + */ +export class CollectionSettings { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + async change(name: 'Collection display name', value: string); + async change(name: 'Collection name', value: string); + async change(name: 'Inherits', value: string[]); + async change(name: 'Categories', value: string[]); + async change(name: 'Description', value: string); + async change(name: 'Generate ID field automatically', value: boolean); + async change(name: 'Store the creation user of each record', value: boolean); + async change(name: 'Store the last update user of each record', value: boolean); + async change(name: 'Store the creation time of each record', value: boolean); + async change(name: 'Store the last update time of each record', value: boolean); + async change(name: 'Records can be sorted', value: boolean); + async change(name: 'File storage', value: string); + async change(name: 'SQL', value: string); + async change(name: string, value: any) { + await this[name](value); + } + + async submit() { + await this.page.getByLabel('action-Action-Submit-').click(); + } + + private async ['SQL'](value: string) { + await this.page.getByLabel('block-item-collections-SQL').getByRole('textbox').fill(value); + await this.page.getByRole('button', { name: 'edit Confirm' }).click(); + } + + private async ['File storage'](value: string) { + await this.page.getByLabel('block-item-Select-collections-File storage').getByTestId('select-single').click(); + await this.page.getByRole('option', { name: value }).click(); + } + + private async ['Collection display name'](value: string) { + await this.page.getByLabel('block-item-Input-collections-Collection display name').getByRole('textbox').fill(value); + } + + private async ['Collection name'](value: string) { + await this.page.getByLabel('block-item-Input-collections-Collection name').getByRole('textbox').fill(value); + } + + private async ['Inherits'](value: string[]) { + // 1. 点击一下打开下拉选项 + await this.page.getByLabel('block-item-Select-collections-Inherits').getByTestId('select-multiple').click(); + + // 2. 点击选择 + for (const name of value) { + await this.page.getByRole('option', { name, exact: true }).click(); + } + + // 3. 关闭下拉选项,以免影响其它操作 + await this.page.getByLabel('block-item-Select-collections-Inherits').getByTestId('select-multiple').click(); + } + + private async ['Categories'](value: string[]) { + // 1. 点击一下打开下拉选项 + await this.page.getByLabel('block-item-Select-collections-Categories').getByTestId('select-multiple').click(); + + // 2. 点击选择 + for (const name of value) { + await this.page.getByRole('option', { name, exact: true }).click(); + } + + // 3. 关闭下拉选项,以免影响其它操作 + await this.page.getByLabel('block-item-Select-collections-Categories').getByTestId('select-multiple').click(); + } + + private async ['Description'](value: string) { + await this.page.getByLabel('block-item-Input.TextArea-').getByRole('textbox').fill(value); + } + + private async ['Generate ID field automatically'](value: boolean) { + await this.page.getByLabel('Generate ID field').setChecked(value); + } + + private async ['Store the creation user of each record'](value: boolean) { + await this.page.getByLabel('Store the creation user of').setChecked(value); + } + + private async ['Store the last update user of each record'](value: boolean) { + await this.page.getByLabel('Store the last update user of').setChecked(value); + } + + private async ['Store the creation time of each record'](value: boolean) { + await this.page.getByLabel('Store the creation time of').setChecked(value); + } + + private async ['Store the last update time of each record'](value: boolean) { + await this.page.getByLabel('Store the last update time of').setChecked(value); + } + + private async ['Records can be sorted'](value: boolean) { + await this.page.getByLabel('Records can be sorted').setChecked(value); + } +} + +export type FieldInterface = + | 'Single line text' + | 'Long text' + | 'Phone' + | 'Email' + | 'URL' + | 'Integer' + | 'Number' + | 'Percent' + | 'Password' + | 'Color' + | 'Icon' + | 'Checkbox' + | 'Single select' + | 'Multiple select' + | 'Radio group' + | 'Checkbox group' + | 'China region' + | 'Markdown' + | 'Rich Text' + | 'Attachment' + | 'Datetime' + | 'Time' + | 'One to one (belongs to)' + | 'One to one (has one)' + | 'One to many' + | 'Many to one' + | 'Many to many' + | 'Formula' + | 'Sequence' + | 'JSON' + | 'Collection' + | 'ID' + | 'Table OID' + | 'Created at' + | 'Last updated at' + | 'Created by' + | 'Last updated by'; + +/** + * 用来配置 Fields + */ +export class FieldsSettings { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + /** + * 对应页面中 Configure fields 弹窗的 Add field 按钮 + * @param fieldInterface + * @returns + */ + async addField(fieldInterface: FieldInterface) { + await this.page.getByRole('button', { name: 'plus Add field' }).hover(); + await this.page.getByRole('menuitem', { name: fieldInterface, exact: true }).click(); + return new FieldSettings(this.page, fieldInterface); + } + + /** + * 对应页面中 configure fields 弹窗的 Edit 按钮 + * @param fieldName + * @param fieldInterface + * @returns + */ + async edit(fieldName: string, fieldInterface: FieldInterface) { + await this.page.getByLabel(`edit-button-${fieldName}`).click(); + return new FieldSettings(this.page, fieldInterface); + } + + /** + * 对应页面中 Configure fields 弹窗中每一行的 Delete 按钮 + * @param fieldName + */ + async deleteItem(fieldName: string) { + await this.page.getByLabel(`action-CollectionFields-Delete-fields-${fieldName}`).click(); + await this.page.getByRole('button', { name: 'OK', exact: true }).click(); + } +} + +/** + * 用来配置 Field + */ +export class FieldSettings { + page: Page; + fieldType: FieldInterface; + + constructor(page: Page, fieldType: FieldInterface) { + this.page = page; + this.fieldType = fieldType; + } + + async change(name: 'Field display name', value: string); + async change(name: 'Field name', value: string); + async change(name: 'Default value', value: string); + async change(name: 'Description', value: string); + async change(name: 'Unique', value: boolean); + async change(name: 'Precision', value: string); + async change(name: 'Options', value: { label: string; value: string; color?: 'Red' | 'Green' | 'Blue' }[]); + async change(name: 'Select level', value: 'Province' | 'City' | 'Area' | 'Street' | 'Village'); + async change(name: 'Must select to the last level', value: boolean); + async change(name: 'MIME type', value: string); + async change(name: 'Allow uploading multiple files', value: boolean); + async change(name: 'Storage', value: string); + async change(name: 'Date format', value: 'Year/Month/Day' | 'Year-Month-Day' | 'Day/Month/Year'); + async change(name: 'Show time', value: boolean); + async change(name: 'GMT', value: boolean); + async change(name: 'Time format', value: '12 hour' | '24 hour'); + async change(name: 'Target collection', value: string); + async change(name: 'Foreign key', value: string); + async change(name: 'ON DELETE', value: string); + async change(name: 'Create inverse field in the target collection', value: boolean); + async change(name: 'Through collection', value: string); + async change(name: 'Foreign key 1', value: string); + async change(name: 'Foreign key 2', value: string); + async change(name: 'Storage type', value: string); + async change(name: 'Calculation engine', value: 'Math.js' | 'Formula.js'); + async change(name: 'Expression', value: string); + async change(name: string, value: any) { + await this[name](value); + } + + async submit() { + await this.page.getByLabel('action-Action-Submit-fields-').click(); + } + + private async ['Field display name'](value: string) { + await this.page.getByLabel('block-item-Input-fields-Field display name').getByRole('textbox').fill(value); + } + + private async ['Field name'](value: string) { + await this.page.getByLabel('block-item-Input-fields-Field name').getByRole('textbox').fill(value); + } + + private async ['Target collection'](value: string) { + await this.page.getByLabel('block-item-Select-fields-Target collection').getByTestId('select-single').click(); + await this.page.getByRole('option', { name: value }).click(); + } + + private async ['Expression'](value: string) { + await this.page.getByLabel('block-item-Formula.Expression').getByLabel('textbox').fill(value); + } +}