fix(defaultValue): fix errors in special cases (#5607)

* fix(defaultValue): fix errors in special cases

* test: add e2e test

* chore: make unit tests pass

* chore: make e2e more stable

* chore: fix e2e
This commit is contained in:
Zeke Zhang 2024-11-07 21:18:59 +08:00 committed by GitHub
parent e70d2d1c9e
commit 5fb6962ec5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 390 additions and 9 deletions

View File

@ -0,0 +1,65 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { expect, test } from '@nocobase/test/e2e';
import { subTableDefaultValue } from './templatesOfBug';
test.describe('subTable', () => {
test('defaultValue', async ({ page, mockPage }) => {
// Default values have been set as:
// staff: {{ $user }}
// timeStart: 2024-11-07
// timeEnd: {{ $iteration.timeStart }}
await mockPage(subTableDefaultValue).goto();
// 1. Click "Add new" to add a row, default values should display correctly
await page.getByRole('button', { name: 'Add new' }).click();
await expect(page.getByTestId('select-object-single').getByText('Super Admin')).toBeVisible();
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').getByPlaceholder('Select date'),
).toHaveValue('2024-11-07');
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').getByPlaceholder('Select date'),
).toHaveValue('2024-11-07');
// 2. Click "Add new" again to add another row, default values should display correctly
await page.getByRole('button', { name: 'Add new' }).click();
await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(1)).toBeVisible();
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(1).getByPlaceholder('Select date'),
).toHaveValue('2024-11-07');
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(1).getByPlaceholder('Select date'),
).toHaveValue('2024-11-07');
// 3. After modifying timeStart in both first and second rows, their corresponding timeEnd should stay synchronized
await page.getByPlaceholder('Select date').first().click();
await page.getByRole('cell', { name: '8', exact: true }).click();
await page.getByPlaceholder('Select date').nth(2).click();
await page.getByRole('cell', { name: '8', exact: true }).click();
// First row
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(0).getByPlaceholder('Select date'),
).toHaveValue('2024-11-08');
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(0).getByPlaceholder('Select date'),
).toHaveValue('2024-11-08');
await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(0)).toBeVisible();
// Second row
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeStart-').nth(1).getByPlaceholder('Select date'),
).toHaveValue('2024-11-08');
await expect(
page.getByLabel('block-item-CollectionField-group-form-group.timeEnd-').nth(1).getByPlaceholder('Select date'),
).toHaveValue('2024-11-08');
await expect(page.getByTestId('select-object-single').getByText('Super Admin').nth(1)).toBeVisible();
});
});

View File

@ -7926,3 +7926,318 @@ export const differentURL_DifferentPopupContent = {
'x-index': 1,
},
};
export const subTableDefaultValue = {
collections: [
{
name: 'people',
fields: [
{
name: 'group',
interface: 'o2m',
target: 'group',
targetKey: 'id',
},
],
},
{
name: 'group',
fields: [
{
name: 'staff',
interface: 'm2o',
target: 'users',
targetKey: 'id',
},
{
name: 'timeStart',
interface: 'datetime',
},
{
name: 'timeEnd',
interface: 'datetime',
},
],
},
],
pageSchema: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Page',
properties: {
gxs8yrx2r0h: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'page:addBlock',
properties: {
'823g8sd0un5': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
'x-app-version': '1.3.46-beta',
properties: {
s8gra6scztq: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
'x-app-version': '1.3.46-beta',
properties: {
k0hmoift98n: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-acl-action-props': {
skipScopeCheck: true,
},
'x-acl-action': 'people:create',
'x-decorator': 'FormBlockProvider',
'x-use-decorator-props': 'useCreateFormBlockDecoratorProps',
'x-decorator-props': {
dataSource: 'main',
collection: 'people',
},
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:createForm',
'x-component': 'CardItem',
'x-app-version': '1.3.46-beta',
properties: {
qj7mcan7daw: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'FormV2',
'x-use-component-props': 'useCreateFormBlockProps',
'x-app-version': '1.3.46-beta',
properties: {
grid: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'form:configureFields',
'x-app-version': '1.3.46-beta',
properties: {
zx4nzvdjpzq: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
'x-app-version': '1.3.46-beta',
properties: {
osnr82axoai: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
'x-app-version': '1.3.46-beta',
properties: {
group: {
'x-uid': '001ix5hsr0t',
_isJSONSchemaObject: true,
version: '2.0',
type: 'string',
'x-toolbar': 'FormItemSchemaToolbar',
'x-settings': 'fieldSettings:FormItem',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
'x-collection-field': 'people.group',
'x-component-props': {
fieldNames: {
label: 'id',
value: 'id',
},
mode: 'SubTable',
},
'x-app-version': '1.3.46-beta',
default: null,
properties: {
'2go92pz3q7s': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'AssociationField.SubTable',
'x-initializer': 'table:configureColumns',
'x-initializer-props': {
action: false,
},
'x-index': 1,
'x-app-version': '1.3.46-beta',
properties: {
'9e59ms847h0': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-decorator': 'TableV2.Column.Decorator',
'x-toolbar': 'TableColumnSchemaToolbar',
'x-settings': 'fieldSettings:TableColumn',
'x-component': 'TableV2.Column',
'x-app-version': '1.3.46-beta',
properties: {
staff: {
'x-uid': 'qfin4x5otua',
_isJSONSchemaObject: true,
version: '2.0',
'x-collection-field': 'group.staff',
'x-component': 'CollectionField',
'x-component-props': {
fieldNames: {
label: 'nickname',
value: 'id',
},
ellipsis: true,
size: 'small',
},
'x-decorator': 'FormItem',
'x-decorator-props': {
labelStyle: {
display: 'none',
},
},
'x-app-version': '1.3.46-beta',
default: '{{$user}}',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'gg09b3sv8p7',
'x-async': false,
'x-index': 1,
},
kd80mzx281w: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-decorator': 'TableV2.Column.Decorator',
'x-toolbar': 'TableColumnSchemaToolbar',
'x-settings': 'fieldSettings:TableColumn',
'x-component': 'TableV2.Column',
'x-app-version': '1.3.46-beta',
properties: {
timeStart: {
'x-uid': 'sm3t7czuvu1',
_isJSONSchemaObject: true,
version: '2.0',
'x-collection-field': 'group.timeStart',
'x-component': 'CollectionField',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-decorator-props': {
labelStyle: {
display: 'none',
},
},
'x-app-version': '1.3.46-beta',
default: '2024-11-06T16:00:00.000Z',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'ojxw1dbkoi0',
'x-async': false,
'x-index': 2,
},
st8bezxhvax: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-decorator': 'TableV2.Column.Decorator',
'x-toolbar': 'TableColumnSchemaToolbar',
'x-settings': 'fieldSettings:TableColumn',
'x-component': 'TableV2.Column',
'x-app-version': '1.3.46-beta',
properties: {
timeEnd: {
'x-uid': '0nks9kfq38u',
_isJSONSchemaObject: true,
version: '2.0',
'x-collection-field': 'group.timeEnd',
'x-component': 'CollectionField',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-decorator-props': {
labelStyle: {
display: 'none',
},
},
'x-app-version': '1.3.46-beta',
default: '{{$iteration.timeStart}}',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '8lynj1uxlbv',
'x-async': false,
'x-index': 3,
},
},
'x-uid': 'bsd9l4pl5by',
'x-async': false,
},
},
'x-async': false,
'x-index': 1,
},
},
'x-uid': 't9bhhahpuln',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'm94ti0kcqqh',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '9po3njajeii',
'x-async': false,
'x-index': 1,
},
gr2fjadfkef: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-initializer': 'createForm:configureActions',
'x-component': 'ActionBar',
'x-component-props': {
layout: 'one-column',
},
'x-app-version': '1.3.46-beta',
'x-uid': 'v5zhsmloels',
'x-async': false,
'x-index': 2,
},
},
'x-uid': 'o9fcw2oo6vi',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '7361xvr7amv',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'an5bhgxdio8',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '0hixaaou1xh',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'nfot2l93mkp',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '3lfdt8s5cay',
'x-async': true,
'x-index': 1,
},
};

View File

@ -72,7 +72,7 @@ describe('isSpecialCaseField', () => {
type: 'hasOne',
};
const fieldSchema: any = {
default: '',
default: '{{ $context }}',
};
const getCollectionField = vi.fn().mockReturnValue(null);
@ -92,7 +92,7 @@ describe('isSpecialCaseField', () => {
},
};
const fieldSchema: any = {
default: '',
default: '{{ $context }}',
parent: parentFieldSchema,
};
@ -116,7 +116,7 @@ describe('isSpecialCaseField', () => {
},
};
const fieldSchema: any = {
default: '',
default: '{{ $context }}',
parent: parentFieldSchema,
};
const getCollectionField = vi.fn().mockReturnValue({

View File

@ -16,8 +16,9 @@ import { useCallback, useEffect } from 'react';
import { useRecordIndex } from '../../../../../src/record-provider';
import { useOperators } from '../../../../block-provider/CollectOperators';
import { useFormBlockContext } from '../../../../block-provider/FormBlockProvider';
import { InheritanceCollectionMixin, useCollection_deprecated } from '../../../../collection-manager';
import { InheritanceCollectionMixin } from '../../../../collection-manager';
import { useCollectionRecord } from '../../../../data-source/collection-record/CollectionRecordProvider';
import { useCollection } from '../../../../data-source/collection/CollectionProvider';
import { DataSourceManager } from '../../../../data-source/data-source/DataSourceManager';
import { useDataSourceManager } from '../../../../data-source/data-source/DataSourceManagerProvider';
import { useFlag } from '../../../../flag-provider';
@ -40,7 +41,7 @@ const useParseDefaultValue = () => {
const record = useCollectionRecord();
const { isInAssignFieldValues, isInSetDefaultValueDialog, isInFormDataTemplate, isInSubTable, isInSubForm } =
useFlag() || {};
const { getField } = useCollection_deprecated();
const collection = useCollection();
const { isSpecialCase, setDefaultValue } = useSpecialCase();
const index = useRecordIndex();
const { type, form } = useFormBlockContext();
@ -92,7 +93,7 @@ const useParseDefaultValue = () => {
}
field.loading = true;
const collectionField = !fieldSchema.name.toString().includes('.') && getField(fieldSchema.name);
const collectionField = !fieldSchema.name.toString().includes('.') && collection?.getField(fieldSchema.name);
if (process.env.NODE_ENV !== 'production') {
if (!collectionField) {
@ -191,7 +192,7 @@ const useParseDefaultValue = () => {
// 解决子表格(或子表单)中新增一行数据时,默认值不生效的问题
field.setValue(fieldSchema.default);
}
}, [fieldSchema.default, localVariables, type, getOperator, dm]);
}, [fieldSchema.default, localVariables, type, getOperator, dm, collection]);
};
export default useParseDefaultValue;

View File

@ -92,8 +92,8 @@ export function isSpecialCaseField({
fieldSchema: Schema;
getCollectionField: (name: string) => CollectionFieldOptions_deprecated;
}) {
// 排除掉“当前对象”这个变量
if (fieldSchema.default.includes('$iteration')) {
// 只针对“表格选中记录”变量有效
if (!fieldSchema.default || !fieldSchema.default.includes('$context')) {
return false;
}