mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-02 04:07:50 +08:00
fix(defaultValue): fix unparsed default value in edit form's subtable (#3289)
* chore: yarn.lock * fix: fix unparsed default value in edit form's subtable * test: fix test * fix: fix T-2805 * chore: increase timeout * chore: increase expect timeout * test: optimize parallelism mode * test: reduce expect timeout * test: mack test more stable * chore: test * chore: test * test: fix parallelism mode * chore: restart
This commit is contained in:
parent
cc251b3222
commit
e99c2f2011
1
.gitignore
vendored
1
.gitignore
vendored
@ -33,6 +33,7 @@ storage/tmp
|
||||
storage/app.watch.ts
|
||||
storage/logs-e2e
|
||||
storage/uploads-e2e
|
||||
storage/.pm2-*
|
||||
tsconfig.paths.json
|
||||
/playwright
|
||||
/storage/playwright
|
||||
|
@ -65,5 +65,5 @@ body a:active {
|
||||
/* fix https://nocobase.height.app/T-2838 */
|
||||
/* antd 组件的层级有问题,有的弹窗是 1000 有的是 1200,会导致弹窗被覆盖的问题。弹窗这里应该使用同一个值,是比较合理的 */
|
||||
.ant-modal-wrap, .ant-modal-mask {
|
||||
z-index: 1000 !important;
|
||||
z-index: 1150 !important;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
const execa = require('execa');
|
||||
const { resolve, dirname } = require('path');
|
||||
const { resolve } = require('path');
|
||||
const pAll = require('p-all');
|
||||
const dotenv = require('dotenv');
|
||||
const fs = require('fs');
|
||||
const { Client } = require('pg');
|
||||
const glob = require('glob');
|
||||
const _ = require('lodash');
|
||||
|
||||
let ENV_FILE = resolve(process.cwd(), '.env.e2e');
|
||||
|
||||
@ -18,7 +19,10 @@ const config = {
|
||||
...process.env,
|
||||
};
|
||||
|
||||
async function runApp(index = 1, dir) {
|
||||
async function runApp(dir, index = 0) {
|
||||
// 一个进程需要占用两个端口? (一个是应用端口,一个是 socket 端口)
|
||||
index = index * 2;
|
||||
|
||||
const database = `nocobase${index}`;
|
||||
const client = new Client({
|
||||
host: config['DB_HOST'],
|
||||
@ -54,15 +58,15 @@ exports.pTest = async (options) => {
|
||||
const files = glob.sync('packages/**/__e2e__/**/*.test.ts', {
|
||||
root: process.cwd(),
|
||||
});
|
||||
const fileSet = new Set();
|
||||
|
||||
for (const file of files) {
|
||||
fileSet.add(dirname(file));
|
||||
}
|
||||
|
||||
const commands = [...fileSet.values()].map((v, i) => {
|
||||
return () => runApp(i + 1, v);
|
||||
const commands = splitArrayIntoParts(files, options.concurrency || 3).map((v, i) => {
|
||||
return () => runApp(v.join(' '), i);
|
||||
});
|
||||
|
||||
await pAll(commands, { concurrency: 3, stopOnError: false, ...options });
|
||||
};
|
||||
|
||||
function splitArrayIntoParts(array, parts) {
|
||||
let chunkSize = Math.ceil(array.length / parts);
|
||||
return _.chunk(array, chunkSize);
|
||||
}
|
||||
|
@ -18,5 +18,31 @@ test.describe('variables with default value', () => {
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||
.getByRole('textbox'),
|
||||
).toHaveValue('1');
|
||||
|
||||
// https://nocobase.height.app/T-2805 ----------------------------------------------------------------------
|
||||
await page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.m2oField0-m2oField0')
|
||||
.getByTestId('select-object-single')
|
||||
.hover();
|
||||
await page.getByLabel('icon-close-select').click();
|
||||
// 等待值消失
|
||||
await page.waitForTimeout(500);
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||
.getByRole('textbox'),
|
||||
).toHaveValue('');
|
||||
|
||||
await page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.m2oField0-m2oField0')
|
||||
.getByTestId('select-object-single')
|
||||
.click();
|
||||
await page.getByRole('option', { name: '1', exact: true }).click();
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||
.getByRole('textbox'),
|
||||
).toHaveValue('1');
|
||||
});
|
||||
});
|
||||
|
@ -584,6 +584,7 @@ test.describe('creation form block schema settings', () => {
|
||||
.getByRole('button', { name: 'designer-schema-settings-TableV2.Column-TableV2.Column.Designer-users' })
|
||||
.hover();
|
||||
await page.getByRole('menuitem', { name: 'Set default value', exact: true }).click();
|
||||
await page.mouse.move(300, 0);
|
||||
await page.getByLabel('Set default value').getByRole('textbox').click();
|
||||
await page.getByLabel('Set default value').getByRole('textbox').fill('test default value');
|
||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||
|
@ -117,7 +117,7 @@ test.describe('table block schema settings', () => {
|
||||
.dragTo(page.getByLabel('table-index-1').getByRole('img', { name: 'menu' }));
|
||||
|
||||
// 等待表格刷新
|
||||
await page.waitForTimeout(2000);
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
email1 = await page.getByText(records[0].email).boundingBox();
|
||||
email2 = await page.getByText(records[1].email).boundingBox();
|
||||
|
@ -5,7 +5,7 @@ export const useStyles = genStyleHook('nb-action-drawer', (token) => {
|
||||
|
||||
return {
|
||||
[componentCls]: {
|
||||
zIndex: '1000 !important', // fix https://nocobase.height.app/T-2797
|
||||
zIndex: '1150 !important', // fix https://nocobase.height.app/T-2797
|
||||
overflow: 'hidden',
|
||||
'&.reset': {
|
||||
'&.nb-action-popup': {
|
||||
|
@ -25,7 +25,7 @@ const useParseDefaultValue = () => {
|
||||
const variables = useVariables();
|
||||
const localVariables = useLocalVariables();
|
||||
const record = useRecord();
|
||||
const { isInAssignFieldValues, isInSetDefaultValueDialog, isInFormDataTemplate } = useFlag() || {};
|
||||
const { isInAssignFieldValues, isInSetDefaultValueDialog, isInFormDataTemplate, isInSubTable } = useFlag() || {};
|
||||
const { getField } = useCollection();
|
||||
const { isSpecialCase, setDefaultValue } = useSpecialCase();
|
||||
const index = useRecordIndex();
|
||||
@ -52,17 +52,21 @@ const useParseDefaultValue = () => {
|
||||
isInFormDataTemplate ||
|
||||
isSubMode(fieldSchema) ||
|
||||
// 编辑状态下不需要设置默认值,否则会覆盖用户输入的值,只有新建状态下才需要设置默认值
|
||||
(formBlockType === 'update' && isFromDatabase(record) && !isInAssignFieldValues)
|
||||
(formBlockType === 'update' && !isInSubTable && isFromDatabase(record) && !isInAssignFieldValues)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const _run = async () => {
|
||||
const _run = async ({ forceUpdate = false } = {}) => {
|
||||
// 如果默认值是一个变量,则需要解析之后再显示出来
|
||||
if (isVariable(fieldSchema.default) && variables && field) {
|
||||
if (
|
||||
variables &&
|
||||
field &&
|
||||
((isVariable(fieldSchema.default) && field.value == null) || field.value === fieldSchema.default || forceUpdate)
|
||||
) {
|
||||
// 一个变量字符串如果显示出来会比较奇怪
|
||||
if (isVariable(field.value)) {
|
||||
field.setValue(null);
|
||||
await field.reset({ forceClear: true });
|
||||
}
|
||||
|
||||
field.loading = true;
|
||||
@ -79,17 +83,16 @@ const useParseDefaultValue = () => {
|
||||
});
|
||||
|
||||
if (value == null || value === '') {
|
||||
field.setValue(null);
|
||||
// fix https://nocobase.height.app/T-2805
|
||||
field.setInitialValue(null);
|
||||
await field.reset({ forceClear: true });
|
||||
} else if (isSpecialCase()) {
|
||||
// 只需要设置一次就可以了
|
||||
if (index === 0) {
|
||||
setDefaultValue(value);
|
||||
}
|
||||
} else {
|
||||
// eslint-disable-next-line promise/catch-or-return
|
||||
Promise.resolve().then(() => {
|
||||
field.setInitialValue(value);
|
||||
});
|
||||
field.setInitialValue(value);
|
||||
}
|
||||
|
||||
field.loading = false;
|
||||
@ -128,13 +131,7 @@ const useParseDefaultValue = () => {
|
||||
|
||||
return value;
|
||||
},
|
||||
_run,
|
||||
{
|
||||
equals: (oldValue, newValue) => {
|
||||
field.setValue(newValue);
|
||||
return oldValue === newValue;
|
||||
},
|
||||
},
|
||||
() => run({ forceUpdate: true }),
|
||||
);
|
||||
|
||||
return dispose;
|
||||
|
@ -2,7 +2,11 @@ import { devices, defineConfig as playwrightDefineConfig, type PlaywrightTestCon
|
||||
|
||||
export const defineConfig = (config?: PlaywrightTestConfig) => {
|
||||
return playwrightDefineConfig({
|
||||
timeout: process.env.CI ? 2 * 60 * 1000 : 30 * 1000,
|
||||
timeout: process.env.CI ? 5 * 60 * 1000 : 30 * 1000,
|
||||
|
||||
expect: {
|
||||
timeout: process.env.CI ? 1 * 60 * 1000 : 5000,
|
||||
},
|
||||
|
||||
// Look for test files in the "tests" directory, relative to this configuration file.
|
||||
testDir: 'packages',
|
||||
|
@ -5834,6 +5834,432 @@ export const oneTableBlockWithAddNewAndViewAndEditAndBasicFields: PageConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 1. 一个 Table 区块
|
||||
* 2. 点击 Add new 有一个 Form 区块,里面有一个 sub-table 字段
|
||||
* 3. 点击 View 有一个 Details 区块,里面有一个 sub-table 字段
|
||||
* 4. 点击 Edit 有一个 Form 区块,里面有一个 sub-table 字段
|
||||
* 5. sub-table 中的所有字段都是 basic 字段
|
||||
*/
|
||||
export const oneTableBlockWithAddNewAndViewAndEditAndBasicFieldsAndSubTable: PageConfig = {
|
||||
collections: [
|
||||
...generalWithBasic,
|
||||
{
|
||||
name: 'subTable',
|
||||
fields: [
|
||||
{
|
||||
name: 'manyToMany',
|
||||
interface: 'm2m',
|
||||
target: 'general',
|
||||
},
|
||||
{
|
||||
name: 'oneToMany',
|
||||
interface: 'o2m',
|
||||
target: 'general',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
pageSchema: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Page',
|
||||
properties: {
|
||||
'7m533o9wcl2': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'BlockInitializers',
|
||||
properties: {
|
||||
mbtse8e9kap: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
ir5rfzx0z5o: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
yr9pww7k8mq: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'TableBlockProvider',
|
||||
'x-acl-action': 'subTable:list',
|
||||
'x-decorator-props': {
|
||||
collection: 'subTable',
|
||||
resource: 'subTable',
|
||||
action: 'list',
|
||||
params: {
|
||||
pageSize: 20,
|
||||
},
|
||||
rowKey: 'id',
|
||||
showIndex: true,
|
||||
dragSort: false,
|
||||
disableTemplate: false,
|
||||
},
|
||||
'x-designer': 'TableBlockDesigner',
|
||||
'x-component': 'CardItem',
|
||||
'x-filter-targets': [],
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-initializer': 'TableActionInitializers',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
style: {
|
||||
marginBottom: 'var(--nb-spacing)',
|
||||
},
|
||||
},
|
||||
'x-uid': '0bvmtmgkrx0',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
'39vo8hzhsor': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'array',
|
||||
'x-initializer': 'TableColumnInitializers',
|
||||
'x-component': 'TableV2',
|
||||
'x-component-props': {
|
||||
rowKey: 'id',
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
useProps: '{{ useTableBlockProps }}',
|
||||
},
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("Actions") }}',
|
||||
'x-action-column': 'actions',
|
||||
'x-decorator': 'TableV2.Column.ActionBar',
|
||||
'x-component': 'TableV2.Column',
|
||||
'x-designer': 'TableV2.ActionColumnDesigner',
|
||||
'x-initializer': 'TableActionColumnInitializers',
|
||||
properties: {
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator': 'DndContext',
|
||||
'x-component': 'Space',
|
||||
'x-component-props': {
|
||||
split: '|',
|
||||
},
|
||||
properties: {
|
||||
dghwbcfocgv: {
|
||||
'x-uid': 'rhc8oxdqglj',
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: 'Edit record',
|
||||
'x-action': 'update',
|
||||
'x-designer': 'Action.Designer',
|
||||
'x-component': 'Action.Link',
|
||||
'x-component-props': {
|
||||
openMode: 'drawer',
|
||||
danger: false,
|
||||
},
|
||||
'x-decorator': 'ACLActionProvider',
|
||||
'x-designer-props': {
|
||||
linkageAction: true,
|
||||
},
|
||||
properties: {
|
||||
drawer: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{ t("Edit record") }}',
|
||||
'x-component': 'Action.Container',
|
||||
'x-component-props': {
|
||||
className: 'nb-action-popup',
|
||||
},
|
||||
properties: {
|
||||
tabs: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
'x-component-props': {},
|
||||
'x-initializer': 'TabPaneInitializers',
|
||||
properties: {
|
||||
tab1: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
title: '{{t("Edit")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-designer': 'Tabs.Designer',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
grid: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'RecordBlockInitializers',
|
||||
properties: {
|
||||
trny88kf0bk: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
'78r8m6ecsh4': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
lj0yhupvh3o: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-acl-action-props': {
|
||||
skipScopeCheck: false,
|
||||
},
|
||||
'x-acl-action': 'subTable:update',
|
||||
'x-decorator': 'FormBlockProvider',
|
||||
'x-decorator-props': {
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
action: 'get',
|
||||
resource: 'subTable',
|
||||
collection: 'subTable',
|
||||
},
|
||||
'x-designer': 'FormV2.Designer',
|
||||
'x-component': 'CardItem',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
'0ykr2ijd1qa': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'FormV2',
|
||||
'x-component-props': {
|
||||
useProps: '{{ useFormBlockProps }}',
|
||||
},
|
||||
properties: {
|
||||
grid: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'FormItemInitializers',
|
||||
properties: {
|
||||
'7mwkv9h74ki': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
'0f4fktqpnee': {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
manyToMany: {
|
||||
'x-uid': 'lclf348ur56',
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'string',
|
||||
'x-designer': 'FormItem.Designer',
|
||||
'x-component': 'CollectionField',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-collection-field':
|
||||
'subTable.manyToMany',
|
||||
'x-component-props': {
|
||||
mode: 'SubTable',
|
||||
},
|
||||
properties: {
|
||||
ry6csw9ij4n: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-component':
|
||||
'AssociationField.SubTable',
|
||||
'x-initializer':
|
||||
'TableColumnInitializers',
|
||||
'x-initializer-props': {
|
||||
action: false,
|
||||
},
|
||||
'x-index': 1,
|
||||
properties: {
|
||||
rmz41gp1stq: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-decorator':
|
||||
'TableV2.Column.Decorator',
|
||||
'x-designer':
|
||||
'TableV2.Column.Designer',
|
||||
'x-component':
|
||||
'TableV2.Column',
|
||||
properties: {
|
||||
singleLineText: {
|
||||
'x-uid': 'tlprzxnyyqb',
|
||||
_isJSONSchemaObject:
|
||||
true,
|
||||
version: '2.0',
|
||||
'x-collection-field':
|
||||
'general.singleLineText',
|
||||
'x-component':
|
||||
'CollectionField',
|
||||
'x-component-props': {
|
||||
ellipsis: true,
|
||||
},
|
||||
'x-decorator':
|
||||
'FormItem',
|
||||
'x-decorator-props': {
|
||||
labelStyle: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
default: null,
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'zmslu38eujy',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'vl5lkem00dr',
|
||||
'x-async': false,
|
||||
},
|
||||
},
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'gzxknc793se',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'lr63kqkjvgo',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': '8iw3zvh7vxd',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
actions: {
|
||||
_isJSONSchemaObject: true,
|
||||
version: '2.0',
|
||||
type: 'void',
|
||||
'x-initializer': 'UpdateFormActionInitializers',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
layout: 'one-column',
|
||||
style: {
|
||||
marginTop: 24,
|
||||
},
|
||||
},
|
||||
'x-uid': '95vrlwf03yk',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': '17ju1kwigyw',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'by4uluzexjq',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'nzw5judm7ah',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'keraakujlcb',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'dtc6ufrnn2w',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'kgrdpc9e834',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'h60qmmbj1ez',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'f930il0aqu3',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': 'gb81ougszo2',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'aa33l45v6qb',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'lm8sj8ojma9',
|
||||
'x-async': false,
|
||||
'x-index': 2,
|
||||
},
|
||||
},
|
||||
'x-uid': 'z5n8ihuvx64',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'snt3mrh4ug9',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'kzi69u1gb24',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'hbmkoataojj',
|
||||
'x-async': false,
|
||||
'x-index': 1,
|
||||
},
|
||||
},
|
||||
'x-uid': 'sfa1nw7kqmi',
|
||||
'x-async': true,
|
||||
'x-index': 1,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* 1. 一个 Table 区块
|
||||
* 2. 点击 Add new 有一个 Form 区块
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { expect, test } from '@nocobase/test/e2e';
|
||||
|
||||
test('menu permission ', async ({ page, mockPage, mockRole, updateRole }) => {
|
||||
const page2 = await mockPage({ name: 'page2' });
|
||||
const page1 = await mockPage({ name: 'page1' });
|
||||
const page2 = mockPage({ name: 'page2' });
|
||||
const page1 = mockPage({ name: 'page1' });
|
||||
await page1.goto();
|
||||
const uid1 = await page1.getUid();
|
||||
const uid2 = await page2.getUid();
|
||||
@ -18,33 +18,29 @@ test('menu permission ', async ({ page, mockPage, mockRole, updateRole }) => {
|
||||
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
|
||||
}, roleData);
|
||||
await page.reload();
|
||||
await expect(await page.getByLabel('page1')).toBeVisible();
|
||||
await expect(await page.getByLabel('page2')).not.toBeVisible();
|
||||
await expect(page.getByLabel('page1')).toBeVisible();
|
||||
await expect(page.getByLabel('page2')).not.toBeVisible();
|
||||
await page.getByTestId('plugin-settings-button').hover();
|
||||
await page.getByLabel('acl').click();
|
||||
await page.getByLabel(`action-Action.Link-Configure-roles-${roleData.name}`).click();
|
||||
await page.getByRole('tab').getByText('Menu permissions').click();
|
||||
await page.waitForSelector('.ant-table');
|
||||
const page1Menu = await page.getByRole('row', { name: 'page1' }).locator('.ant-checkbox-input');
|
||||
const page2Menu = await page.getByRole('row', { name: 'page2' }).locator('.ant-checkbox-input');
|
||||
await expect(await page1Menu.isChecked()).toBe(true);
|
||||
await expect(await page2Menu.isChecked()).toBe(false);
|
||||
await expect(page.getByRole('row', { name: 'page1' }).locator('.ant-checkbox-input')).toBeChecked({ checked: true });
|
||||
await expect(page.getByRole('row', { name: 'page2' }).locator('.ant-checkbox-input')).toBeChecked({ checked: false });
|
||||
//修改菜单权限,page1无权限,page2有权限
|
||||
await updateRole({ name: roleData.name, menuUiSchemas: [uid2] });
|
||||
await page.reload();
|
||||
await expect(await page.getByLabel('page2')).toBeVisible();
|
||||
await expect(await page.getByLabel('page1')).not.toBeVisible();
|
||||
await expect(page.getByLabel('page2')).toBeVisible();
|
||||
await expect(page.getByLabel('page1')).not.toBeVisible();
|
||||
await page.getByTestId('plugin-settings-button').hover();
|
||||
await page.getByLabel('acl').click();
|
||||
await page.getByLabel(`action-Action.Link-Configure-roles-${roleData.name}`).click();
|
||||
await page.getByRole('tab').getByText('Menu permissions').click();
|
||||
await page.waitForSelector('.ant-table');
|
||||
const page1Menu1 = await page.getByRole('row', { name: 'page1' }).locator('.ant-checkbox-input');
|
||||
const page2Menu1 = await page.getByRole('row', { name: 'page2' }).locator('.ant-checkbox-input');
|
||||
await expect(await page1Menu1.isChecked()).toBe(false);
|
||||
await expect(await page2Menu1.isChecked()).toBe(true);
|
||||
await expect(page.getByRole('row', { name: 'page1' }).locator('.ant-checkbox-input')).toBeChecked({ checked: false });
|
||||
await expect(page.getByRole('row', { name: 'page2' }).locator('.ant-checkbox-input')).toBeChecked({ checked: true });
|
||||
//通过路由访问无权限的菜单,跳到有权限的第一个菜单
|
||||
await page.goto(`/admin/${uid1}`);
|
||||
await page.waitForSelector('.nb-page-wrapper');
|
||||
await expect(await page.url()).toContain(uid2);
|
||||
expect(page.url()).toContain(uid2);
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ test.describe('TableActionInitializers & GanttActionInitializers & MapActionInit
|
||||
await page.getByRole('menuitem', { name: 'Customize right' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Bulk edit' }).click();
|
||||
await page.mouse.move(300, 0);
|
||||
await expect(await page.getByLabel('Bulk edit')).toBeVisible();
|
||||
await expect(page.getByLabel('Bulk edit')).toBeVisible();
|
||||
});
|
||||
test('bulk edit in GanttActionInitializers', async ({ page, mockPage, mockRecords }) => {
|
||||
const nocoPage = await mockPage(oneEmptyGantt).waitForInit();
|
||||
@ -17,6 +17,6 @@ test.describe('TableActionInitializers & GanttActionInitializers & MapActionInit
|
||||
await page.getByLabel('schema-initializer-ActionBar-GanttActionInitializers-general').hover();
|
||||
await page.getByRole('menuitem', { name: 'Customize right' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Bulk edit' }).click();
|
||||
await expect(await page.getByLabel('Bulk edit')).toBeVisible();
|
||||
await expect(page.getByLabel('Bulk edit')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
@ -14,9 +14,9 @@ test.describe('TableActionColumnInitializers & DetailsActionInitializers & ReadP
|
||||
await page.getByRole('button', { name: 'Actions' }).hover();
|
||||
await page.getByLabel('designer-schema-settings-TableV2.Column-TableV2.ActionColumnDesigner-general').hover();
|
||||
await page.getByRole('menuitem', { name: 'Duplicate' }).click();
|
||||
await expect(await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
await expect(page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
});
|
||||
test('duplication action in DetailsActionInitializers', async ({ page, mockPage, mockCollections, mockRecords }) => {
|
||||
test('duplication action in DetailsActionInitializers', async ({ page, mockPage }) => {
|
||||
await mockPage(oneEmptyDetailsBlock).goto();
|
||||
await page.getByLabel('schema-initializer-ActionBar-DetailsActionInitializers-general').click();
|
||||
await page.getByRole('menuitem', { name: 'Duplicate' }).click();
|
||||
|
@ -2,11 +2,11 @@ import { expect, test } from '@nocobase/test/e2e';
|
||||
import { oneEmptyTableBlockWithDuplicateActions } from './utils';
|
||||
|
||||
test.describe('direct duplicate & copy into the form and continue to fill in', () => {
|
||||
test('direct duplicate', async ({ page, mockPage, mockCollections, mockRecords }) => {
|
||||
test('direct duplicate', async ({ page, mockPage, mockRecords }) => {
|
||||
const nocoPage = await mockPage(oneEmptyTableBlockWithDuplicateActions).waitForInit();
|
||||
const data = await mockRecords('general', 3);
|
||||
await nocoPage.goto();
|
||||
await expect(await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
await expect(page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0').hover();
|
||||
await page.getByRole('button', { name: 'designer-schema-settings-Action.Link-Action.Designer-general' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Duplicate mode' }).click();
|
||||
@ -26,7 +26,7 @@ test.describe('direct duplicate & copy into the form and continue to fill in', (
|
||||
const nocoPage = await mockPage(oneEmptyTableBlockWithDuplicateActions).waitForInit();
|
||||
const data = await mockRecord('general');
|
||||
await nocoPage.goto();
|
||||
await expect(await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
await expect(page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0')).toBeVisible();
|
||||
await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0').hover();
|
||||
await page.getByRole('button', { name: 'designer-schema-settings-Action.Link-Action.Designer-general' }).hover();
|
||||
await page.getByRole('menuitem', { name: 'Duplicate mode' }).click();
|
||||
@ -71,11 +71,8 @@ test.describe('direct duplicate & copy into the form and continue to fill in', (
|
||||
|
||||
await page.getByLabel('action-Action.Link-Duplicate-duplicate-general-table-0').click();
|
||||
await expect(
|
||||
await page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText')
|
||||
.getByRole('textbox')
|
||||
.inputValue(),
|
||||
).toBe(data['singleLineText']);
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.singleLineText').getByRole('textbox'),
|
||||
).toHaveValue(data['singleLineText']);
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest((request) => request.url().includes('api/general:create')),
|
||||
page.getByLabel('action-Action-Submit-submit-general-form').click(),
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
expect,
|
||||
expectSettingsMenu,
|
||||
oneTableBlockWithAddNewAndViewAndEditAndBasicFields,
|
||||
oneTableBlockWithAddNewAndViewAndEditAndBasicFieldsAndSubTable,
|
||||
test,
|
||||
} from '@nocobase/test/e2e';
|
||||
import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern, testSetValidationRules } from '../../utils';
|
||||
@ -37,23 +38,20 @@ test.describe('form item & create form', () => {
|
||||
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),
|
||||
gotoPage: async () => {
|
||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFields).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 (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'),
|
||||
showMenu: async () => {
|
||||
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();
|
||||
},
|
||||
supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'],
|
||||
constantValue: 'test single line text',
|
||||
variableValue: ['Current user', 'Email'], // 值为 admin@nocobase.com
|
||||
@ -374,3 +372,68 @@ test.describe('table column & table', () => {
|
||||
await expect(page.getByRole('columnheader', { name: 'singleLineText' })).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('table column & sub-table in edit form', () => {
|
||||
test('supported options', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFieldsAndSubTable).waitForInit();
|
||||
await mockRecord('subTable');
|
||||
await nocoPage.goto();
|
||||
|
||||
await expectSettingsMenu({
|
||||
page,
|
||||
showMenu: async () => {
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-subTable-table-0').click();
|
||||
await page.getByRole('button', { name: 'singleLineText', exact: true }).hover();
|
||||
await page.getByLabel('designer-schema-settings-TableV2.Column-TableV2.Column.Designer-general').hover();
|
||||
},
|
||||
supportedOptions: ['Custom column title', 'Column width', 'Required', 'Pattern', 'Set default value', 'Delete'],
|
||||
});
|
||||
});
|
||||
|
||||
test('set default value', async ({ page, mockPage, mockRecord }) => {
|
||||
let record;
|
||||
await testDefaultValue({
|
||||
page,
|
||||
gotoPage: async () => {
|
||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndBasicFieldsAndSubTable).waitForInit();
|
||||
record = await mockRecord('subTable');
|
||||
await nocoPage.goto();
|
||||
},
|
||||
openDialog: async () => {
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-subTable-table-0').click();
|
||||
},
|
||||
closeDialog: async () => {
|
||||
await page.getByLabel('drawer-Action.Container-subTable-Edit record-mask').click();
|
||||
},
|
||||
showMenu: async () => {
|
||||
await page.getByRole('button', { name: 'singleLineText', exact: true }).hover();
|
||||
await page.getByLabel('designer-schema-settings-TableV2.Column-TableV2.Column.Designer-general').hover();
|
||||
},
|
||||
supportVariables: [
|
||||
'Constant',
|
||||
'Current user',
|
||||
'Current role',
|
||||
'Current form',
|
||||
'Current object',
|
||||
'Current record',
|
||||
],
|
||||
variableValue: ['Current user', 'Nickname'],
|
||||
expectVariableValue: async () => {
|
||||
await page.getByRole('button', { name: 'plus' }).click();
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||
.nth(0)
|
||||
.getByRole('textbox'),
|
||||
).toHaveValue(record.manyToMany[0].singleLineText);
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||
.nth(record.manyToMany.length) // 最后一行
|
||||
.getByRole('textbox'),
|
||||
).toHaveValue('Super Admin');
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -36,7 +36,7 @@ test.describe('configure setting', () => {
|
||||
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.getByTitle('ID').click();
|
||||
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
|
||||
await page.getByRole('spinbutton').fill('1');
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest((request) => request.url().includes('api/general:list')),
|
||||
|
@ -4215,11 +4215,6 @@
|
||||
dependencies:
|
||||
eslint-scope "5.1.1"
|
||||
|
||||
"@nocobase/plugin-workflow-test@>=0.17.0-alpha.3":
|
||||
version "0.17.0-alpha.7"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/plugin-workflow-test/-/plugin-workflow-test-0.17.0-alpha.7.tgz#219a3a1e91e51bec08b1adbb1c4c5c9c7184ecce"
|
||||
integrity sha512-krZlo1xDM66spbQG6jAYSraxazuxCuA2rD9TxptFQXjkAMTGkuDilJ+edMj6p866N3nyzvFh8lZ2/XY1HUC7Xw==
|
||||
|
||||
"@node-saml/node-saml@^4.0.2":
|
||||
version "4.0.5"
|
||||
resolved "https://registry.npmmirror.com/@node-saml/node-saml/-/node-saml-4.0.5.tgz#039e387095b54639b06df62b1b4a6d8941c6d907"
|
||||
|
Loading…
Reference in New Issue
Block a user