fix(LinkageRules): should work properly after the block is saved as a template (#3855)

* test: add e2e

* chore: optimize e2e

* fix: use context in Form
This commit is contained in:
Zeke Zhang 2024-03-28 22:03:22 +08:00 committed by GitHub
parent 44e7f48f99
commit 08162e1004
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 246 additions and 2 deletions

View File

@ -9,7 +9,7 @@ import {
oneTableBlockWithAddNewAndViewAndEditAndBasicFields, oneTableBlockWithAddNewAndViewAndEditAndBasicFields,
test, test,
} from '@nocobase/test/e2e'; } from '@nocobase/test/e2e';
import { T2165, T2174, T3251 } from './templatesOfBug'; import { T2165, T2174, T3251, T3806 } from './templatesOfBug';
const clickOption = async (page: Page, optionName: string) => { const clickOption = async (page: Page, optionName: string) => {
await page.getByLabel('block-item-CardItem-general-form').hover(); await page.getByLabel('block-item-CardItem-general-form').hover();
@ -254,6 +254,47 @@ test.describe('creation form block schema settings', () => {
page.getByLabel('block-item-CollectionField-users-form-users.email-Email').getByRole('textbox'), page.getByLabel('block-item-CollectionField-users-form-users.email-Email').getByRole('textbox'),
).toBeEditable(); ).toBeEditable();
}); });
// https://nocobase.height.app/T-3806
test('after save as block template', async ({ page, mockPage }) => {
await mockPage(T3806).goto();
// 1. 一开始联动规则应该正常
await page
.getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname')
.getByRole('textbox')
.fill('123');
await expect(
page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'),
).toHaveValue('123');
try {
// 2. 将表单区块保存为模板后
await page.getByLabel('block-item-CardItem-users-form').hover();
await page.getByLabel('designer-schema-settings-CardItem-blockSettings:createForm-users').hover();
await page.getByRole('menuitem', { name: 'Save as block template' }).click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await page.waitForTimeout(1000);
// 3. 联动规则应该依然是正常的
await page
.getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname')
.getByRole('textbox')
.fill('456');
await expect(
page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'),
).toHaveValue('456');
} catch (err) {
throw err;
} finally {
// 4. 把创建的模板删除
await page.goto('/admin/settings/ui-schema-storage');
await page.getByLabel('Select all').check();
await page.getByLabel('action-Action-Delete-destroy-').click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await expect(page.getByRole('row', { name: 'Users_Form' }).first()).toBeHidden();
}
});
}); });
test('Save as block template & convert reference to duplicate', async ({ page, mockPage }) => { test('Save as block template & convert reference to duplicate', async ({ page, mockPage }) => {

View File

@ -6066,3 +6066,204 @@ export const T3529: PageConfig = {
'x-index': 1, 'x-index': 1,
}, },
}; };
export const T3806: PageConfig = {
pageSchema: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Page',
properties: {
'6w8tkq3665g': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'page:addBlock',
properties: {
'0k0yifwylj8': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
properties: {
v5cdqnvyh3z: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
p9pszqbz1n5: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-acl-action-props': {
skipScopeCheck: true,
},
'x-acl-action': 'users:create',
'x-decorator': 'FormBlockProvider',
'x-use-decorator-props': 'useCreateFormBlockDecoratorProps',
'x-decorator-props': {
dataSource: 'main',
collection: 'users',
},
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:createForm',
'x-component': 'CardItem',
properties: {
'578cg3ao40s': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'FormV2',
'x-use-component-props': 'useCreateFormBlockProps',
properties: {
grid: {
'x-uid': 'xpdqjz634mt',
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'form:configureFields',
'x-linkage-rules': [
{
condition: {
$and: [],
},
actions: [
{
targetFields: ['username'],
operator: 'value',
value: {
mode: 'express',
value: '{{$nForm.nickname}}',
result: '{{$nForm.nickname}}',
},
},
],
},
],
properties: {
gjck905cyws: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
properties: {
i041myizzph: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
nickname: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'string',
'x-toolbar': 'FormItemSchemaToolbar',
'x-settings': 'fieldSettings:FormItem',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
'x-collection-field': 'users.nickname',
'x-component-props': {},
'x-uid': 'afnfoxl5cbi',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'a3o7l08zz6e',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'zoakp82dymw',
'x-async': false,
'x-index': 1,
},
qffoo7lqua1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
properties: {
nq0rbuti1d9: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
username: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'string',
'x-toolbar': 'FormItemSchemaToolbar',
'x-settings': 'fieldSettings:FormItem',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
'x-collection-field': 'users.username',
'x-component-props': {},
'x-uid': 'mq80n8nyuq8',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'hf9bq4vjm80',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'ua08izsl514',
'x-async': false,
'x-index': 2,
},
},
'x-async': false,
'x-index': 1,
},
'006ip4mnr75': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-initializer': 'createForm:configureActions',
'x-component': 'ActionBar',
'x-component-props': {
layout: 'one-column',
style: {
marginTop: 24,
},
},
'x-uid': 'u6d026lia1x',
'x-async': false,
'x-index': 2,
},
},
'x-uid': 'p7ucl8ixcx4',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'hz9xoui3o9d',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'j1q201o2wju',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 't0olm6ygvas',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'aq4i1y0nf00',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'px8uapyslvw',
'x-async': true,
'x-index': 1,
},
};

View File

@ -19,6 +19,7 @@ import { getInnermostKeyAndValue, getTargetField } from '../../common/utils/uitl
import { useProps } from '../../hooks/useProps'; import { useProps } from '../../hooks/useProps';
import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils'; import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils';
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps'; import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider';
export interface FormProps { export interface FormProps {
[key: string]: any; [key: string]: any;
@ -87,6 +88,7 @@ const WithForm = (props: WithFormProps) => {
const { setFormValueChanged } = useActionContext(); const { setFormValueChanged } = useActionContext();
const variables = useVariables(); const variables = useVariables();
const localVariables = useLocalVariables({ currentForm: form }); const localVariables = useLocalVariables({ currentForm: form });
const { templateFinshed } = useTemplateBlockContext();
const linkageRules: any[] = const linkageRules: any[] =
(getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || []; (getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || [];
@ -166,7 +168,7 @@ const WithForm = (props: WithFormProps) => {
dispose(); dispose();
}); });
}; };
}, [linkageRules]); }, [linkageRules, templateFinshed]);
return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />; return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />;
}; };