@skopon-cool/form-sdk 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog/useSkoponBoundField.d.ts +14 -2
- package/dist/catalog/useSkoponBoundField.d.ts.map +1 -1
- package/dist/index.js +717 -710
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts +7 -1
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/catalog/useSkoponBoundField.test.ts +30 -5
- package/src/catalog/useSkoponBoundField.ts +21 -7
- package/src/submit/intersectPayloadBlocksWithForm.ts +52 -25
- package/src/submit/submit.test.ts +128 -3
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { FormBlock, FormSchema } from '../types/index';
|
|
2
|
-
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'blocks'
|
|
2
|
+
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'blocks'> & {
|
|
3
|
+
/**
|
|
4
|
+
* ask 原始 blocks(normalize 前)。交集合并按此键集覆盖 form,
|
|
5
|
+
* 避免 normalize 填入的空默认值误盖表单样式。
|
|
6
|
+
*/
|
|
7
|
+
rawBlocks?: FormBlock[];
|
|
8
|
+
};
|
|
3
9
|
export interface PayloadBlocksIntersection {
|
|
4
10
|
matchedBlocks: FormBlock[];
|
|
5
11
|
extraBlocks: FormBlock[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,GAAG;IAC3F;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,0DAA0D;IAC1D,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAuED,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAmBvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,GACrC,yBAAyB,CA+B3B;AA+BD,2CAA2C;AAC3C,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzF;AAED,sDAAsD;AACtD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAIlF;AAED,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,EAAE,CAK3F;AAED,mDAAmD;AACnD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,EAAE,CAIvF"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { describe, it, expect } from 'vitest'
|
|
5
5
|
import type { ComponentContext } from '@a2ui/web_core/v0_9'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
asStringArray,
|
|
8
|
+
clampStringArraySelection,
|
|
9
|
+
isCardSelectionDisabled,
|
|
10
|
+
normalizeSelectStoredValue,
|
|
11
|
+
readBoundFieldValue,
|
|
12
|
+
toggleStringArraySelection,
|
|
13
|
+
} from './useSkoponBoundField'
|
|
7
14
|
|
|
8
15
|
function createMockContext(initial: unknown = []): {
|
|
9
16
|
context: ComponentContext
|
|
@@ -61,12 +68,16 @@ describe('readBoundFieldValue', () => {
|
|
|
61
68
|
})
|
|
62
69
|
|
|
63
70
|
describe('toggleStringArraySelection', () => {
|
|
64
|
-
it('
|
|
65
|
-
expect(toggleStringArraySelection(['a'], 'b',
|
|
71
|
+
it('replaces selection when maxCount is 1', () => {
|
|
72
|
+
expect(toggleStringArraySelection(['a'], 'b', 1, 1)).toEqual(['b'])
|
|
66
73
|
})
|
|
67
74
|
|
|
68
|
-
it('blocks
|
|
69
|
-
expect(toggleStringArraySelection(['a'], '
|
|
75
|
+
it('blocks append when at maxCount greater than 1', () => {
|
|
76
|
+
expect(toggleStringArraySelection(['a', 'b'], 'c', undefined, 2)).toBeNull()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('allows deselect even when at minCount', () => {
|
|
80
|
+
expect(toggleStringArraySelection(['a'], 'a', 1, undefined)).toEqual([])
|
|
70
81
|
})
|
|
71
82
|
|
|
72
83
|
it('allows toggle within bounds', () => {
|
|
@@ -75,6 +86,20 @@ describe('toggleStringArraySelection', () => {
|
|
|
75
86
|
})
|
|
76
87
|
})
|
|
77
88
|
|
|
89
|
+
describe('isCardSelectionDisabled', () => {
|
|
90
|
+
it('keeps selected cards clickable under minCount', () => {
|
|
91
|
+
expect(isCardSelectionDisabled(['a'], 'a', true, 1, 1)).toBe(false)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('keeps unselected cards clickable when maxCount is 1', () => {
|
|
95
|
+
expect(isCardSelectionDisabled(['a'], 'b', true, 1, 1)).toBe(false)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('disables unselected cards when maxCount greater than 1 is full', () => {
|
|
99
|
+
expect(isCardSelectionDisabled(['a', 'b'], 'c', true, undefined, 2)).toBe(true)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
78
103
|
describe('clampStringArraySelection', () => {
|
|
79
104
|
it('returns null when within maxCount', () => {
|
|
80
105
|
expect(clampStringArraySelection(['a'], 2)).toBeNull()
|
|
@@ -203,33 +203,47 @@ export function readOptionalSelectCount(value: unknown): number | undefined {
|
|
|
203
203
|
return Math.floor(num)
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
/**
|
|
207
|
+
* 切换多选选中态。
|
|
208
|
+
* - 已选项:始终允许取消(minCount 仅提交校验)
|
|
209
|
+
* - maxCount === 1:点未选项直接替换为 [itemId]
|
|
210
|
+
* - maxCount > 1 且已满:阻止追加
|
|
211
|
+
*/
|
|
206
212
|
export function toggleStringArraySelection(
|
|
207
213
|
selectedIds: string[],
|
|
208
214
|
itemId: string,
|
|
209
|
-
|
|
215
|
+
_minCount: number | undefined,
|
|
210
216
|
maxCount: number | undefined,
|
|
211
217
|
): string[] | null {
|
|
212
218
|
const isSelected = selectedIds.includes(itemId)
|
|
213
219
|
if (isSelected) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
220
|
+
return selectedIds.filter((id) => id !== itemId)
|
|
221
|
+
}
|
|
222
|
+
if (maxCount === 1) {
|
|
223
|
+
return [itemId]
|
|
217
224
|
}
|
|
218
225
|
if (maxCount !== undefined && selectedIds.length >= maxCount) return null
|
|
219
226
|
return [...selectedIds, itemId]
|
|
220
227
|
}
|
|
221
228
|
|
|
229
|
+
/**
|
|
230
|
+
* 卡片是否禁用点击。
|
|
231
|
+
* - 已选项始终可点(允许取消);minCount 不在此强制
|
|
232
|
+
* - maxCount === 1 时未选项可点(用于替换)
|
|
233
|
+
* - maxCount > 1 且已满时未选项禁用
|
|
234
|
+
*/
|
|
222
235
|
export function isCardSelectionDisabled(
|
|
223
236
|
selectedIds: string[],
|
|
224
237
|
itemId: string,
|
|
225
238
|
interactive: boolean,
|
|
226
|
-
|
|
239
|
+
_minCount: number | undefined,
|
|
227
240
|
maxCount: number | undefined,
|
|
228
241
|
): boolean {
|
|
229
242
|
if (!interactive) return true
|
|
230
243
|
const isSelected = selectedIds.includes(itemId)
|
|
231
|
-
if (
|
|
232
|
-
if (
|
|
244
|
+
if (isSelected) return false
|
|
245
|
+
if (maxCount === 1) return false
|
|
246
|
+
if (maxCount !== undefined && selectedIds.length >= maxCount) return true
|
|
233
247
|
return false
|
|
234
248
|
}
|
|
235
249
|
|
|
@@ -2,7 +2,13 @@ import { normalizeFormDefinition } from '../adapter/formSchema'
|
|
|
2
2
|
import type { FormBlock, FormSchema } from '../types/index'
|
|
3
3
|
import { isInputBlockType, isLayoutBlockType } from '../types/index'
|
|
4
4
|
|
|
5
|
-
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'blocks'>
|
|
5
|
+
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'blocks'> & {
|
|
6
|
+
/**
|
|
7
|
+
* ask 原始 blocks(normalize 前)。交集合并按此键集覆盖 form,
|
|
8
|
+
* 避免 normalize 填入的空默认值误盖表单样式。
|
|
9
|
+
*/
|
|
10
|
+
rawBlocks?: FormBlock[]
|
|
11
|
+
}
|
|
6
12
|
|
|
7
13
|
export interface PayloadBlocksIntersection {
|
|
8
14
|
matchedBlocks: FormBlock[]
|
|
@@ -13,6 +19,8 @@ export interface PayloadBlocksIntersection {
|
|
|
13
19
|
description: string
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
const FORM_ANCHORED_KEYS = new Set(['type', 'name', 'id'])
|
|
23
|
+
|
|
16
24
|
function normalizePayloadBlock(block: FormBlock): FormBlock {
|
|
17
25
|
return normalizeFormDefinition({
|
|
18
26
|
title: '',
|
|
@@ -47,21 +55,37 @@ function buildRenderBlocks(
|
|
|
47
55
|
return renderBlocks
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
function resolveRawInputBlock(
|
|
59
|
+
payloadDef: PayloadBlocksDefinition,
|
|
60
|
+
name: string,
|
|
61
|
+
fallback: FormBlock,
|
|
62
|
+
): FormBlock {
|
|
63
|
+
const rawBlocks = payloadDef.rawBlocks
|
|
64
|
+
if (!rawBlocks?.length) return fallback
|
|
65
|
+
for (const block of rawBlocks) {
|
|
66
|
+
if (!block || typeof block !== 'object') continue
|
|
67
|
+
const blockName = typeof block.name === 'string' ? block.name.trim() : ''
|
|
68
|
+
if (blockName === name) return block
|
|
55
69
|
}
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
return fallback
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 交集块:form 锚定 type/name/id;ask 原始 block 上显式出现的其余字段覆盖 form。
|
|
75
|
+
*/
|
|
76
|
+
function mergeBlock(formBlock: FormBlock, rawPayloadBlock: FormBlock): FormBlock {
|
|
77
|
+
const merged: FormBlock = { ...formBlock }
|
|
78
|
+
for (const key of Object.keys(rawPayloadBlock) as (keyof FormBlock)[]) {
|
|
79
|
+
if (FORM_ANCHORED_KEYS.has(key)) continue
|
|
80
|
+
if (!Object.prototype.hasOwnProperty.call(rawPayloadBlock, key)) continue
|
|
81
|
+
const value = rawPayloadBlock[key]
|
|
82
|
+
if (value === undefined) continue
|
|
83
|
+
Object.assign(merged, { [key]: value })
|
|
58
84
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
jsonSchema: {},
|
|
64
|
-
}).blocks[0]!
|
|
85
|
+
merged.type = formBlock.type
|
|
86
|
+
merged.name = formBlock.name?.trim() || rawPayloadBlock.name
|
|
87
|
+
merged.id = formBlock.id
|
|
88
|
+
return normalizePayloadBlock(merged)
|
|
65
89
|
}
|
|
66
90
|
|
|
67
91
|
/** 解析 ask_user payload 为 blocksJson 形(title / description / blocks) */
|
|
@@ -69,12 +93,21 @@ export function parsePayloadBlocksJson(payload: unknown): PayloadBlocksDefinitio
|
|
|
69
93
|
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return null
|
|
70
94
|
const obj = payload as Record<string, unknown>
|
|
71
95
|
if (!Array.isArray(obj.blocks)) return null
|
|
72
|
-
|
|
96
|
+
const rawBlocks = obj.blocks.filter(
|
|
97
|
+
(block): block is FormBlock => Boolean(block) && typeof block === 'object' && !Array.isArray(block),
|
|
98
|
+
) as FormBlock[]
|
|
99
|
+
const normalized = normalizeFormDefinition({
|
|
73
100
|
title: typeof obj.title === 'string' ? obj.title : '',
|
|
74
101
|
description: typeof obj.description === 'string' ? obj.description : '',
|
|
75
|
-
blocks:
|
|
102
|
+
blocks: rawBlocks,
|
|
76
103
|
jsonSchema: {},
|
|
77
104
|
})
|
|
105
|
+
return {
|
|
106
|
+
title: normalized.title,
|
|
107
|
+
description: normalized.description,
|
|
108
|
+
blocks: normalized.blocks,
|
|
109
|
+
rawBlocks,
|
|
110
|
+
}
|
|
78
111
|
}
|
|
79
112
|
|
|
80
113
|
/**
|
|
@@ -101,16 +134,10 @@ export function intersectPayloadBlocksWithForm(
|
|
|
101
134
|
if (!name) continue
|
|
102
135
|
const formBlock = formByName.get(name)
|
|
103
136
|
if (formBlock) {
|
|
104
|
-
|
|
137
|
+
const rawPayloadBlock = resolveRawInputBlock(payloadDef, name, payloadBlock)
|
|
138
|
+
matchedBlocks.push(mergeBlock(formBlock, rawPayloadBlock))
|
|
105
139
|
} else {
|
|
106
|
-
extraBlocks.push(
|
|
107
|
-
normalizeFormDefinition({
|
|
108
|
-
title: '',
|
|
109
|
-
description: '',
|
|
110
|
-
blocks: [payloadBlock],
|
|
111
|
-
jsonSchema: {},
|
|
112
|
-
}).blocks[0]!,
|
|
113
|
-
)
|
|
140
|
+
extraBlocks.push(normalizePayloadBlock(payloadBlock))
|
|
114
141
|
}
|
|
115
142
|
}
|
|
116
143
|
|
|
@@ -176,7 +176,7 @@ describe('intersectPayloadBlocksWithForm', () => {
|
|
|
176
176
|
expect(extractExtraBlockValues(extraBlocks)).toEqual({ resumes: [] })
|
|
177
177
|
})
|
|
178
178
|
|
|
179
|
-
it('keeps form
|
|
179
|
+
it('keeps form type/name/id and overlays explicit ask fields when payload type differs', () => {
|
|
180
180
|
const selectForm: FormSchema = {
|
|
181
181
|
title: 'Form',
|
|
182
182
|
description: '',
|
|
@@ -209,7 +209,8 @@ describe('intersectPayloadBlocksWithForm', () => {
|
|
|
209
209
|
const result = intersectPayloadBlocksWithForm(mismatchedPayload, selectForm)
|
|
210
210
|
expect(result.matchedBlocks).toHaveLength(1)
|
|
211
211
|
expect(result.matchedBlocks[0]?.type).toBe('select')
|
|
212
|
-
expect(result.matchedBlocks[0]?.
|
|
212
|
+
expect(result.matchedBlocks[0]?.id).toBe('1')
|
|
213
|
+
expect(result.matchedBlocks[0]?.label).toBe('Payload Label')
|
|
213
214
|
expect(result.matchedBlocks[0]?.options).toEqual([
|
|
214
215
|
{ label: 'A', value: 'a' },
|
|
215
216
|
{ label: 'B', value: 'b' },
|
|
@@ -217,6 +218,130 @@ describe('intersectPayloadBlocksWithForm', () => {
|
|
|
217
218
|
expect(result.matchedBlocks[0]?.defaultValue).toBe('a')
|
|
218
219
|
})
|
|
219
220
|
|
|
221
|
+
it('keeps form label when ask only provides name and defaultValue', () => {
|
|
222
|
+
const form: FormSchema = {
|
|
223
|
+
title: 'Form',
|
|
224
|
+
description: '',
|
|
225
|
+
blocks: [{ id: '1', type: 'text', name: 'video_title', label: 'Form Title', help: 'Form help' }],
|
|
226
|
+
jsonSchema: {},
|
|
227
|
+
}
|
|
228
|
+
const payloadDef = parsePayloadBlocksJson({
|
|
229
|
+
title: 'Ask',
|
|
230
|
+
blocks: [{ id: 'p1', type: 'text', name: 'video_title', defaultValue: 'hello' }],
|
|
231
|
+
})!
|
|
232
|
+
const result = intersectPayloadBlocksWithForm(payloadDef, form)
|
|
233
|
+
expect(result.matchedBlocks[0]?.label).toBe('Form Title')
|
|
234
|
+
expect(result.matchedBlocks[0]?.help).toBe('Form help')
|
|
235
|
+
expect(result.matchedBlocks[0]?.defaultValue).toBe('hello')
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it('overlays ask caseFilter over form caseFilter', () => {
|
|
239
|
+
const form: FormSchema = {
|
|
240
|
+
title: 'Form',
|
|
241
|
+
description: '',
|
|
242
|
+
blocks: [
|
|
243
|
+
{
|
|
244
|
+
id: '1',
|
|
245
|
+
type: 'case_multiselect',
|
|
246
|
+
name: 'selected_cases',
|
|
247
|
+
label: 'Form Cases',
|
|
248
|
+
caseMinCount: 1,
|
|
249
|
+
caseMaxCount: 1,
|
|
250
|
+
caseFilter: {
|
|
251
|
+
agentUniqueId: 'agent-form',
|
|
252
|
+
flowType: 'service',
|
|
253
|
+
category: 'cat-form',
|
|
254
|
+
flowUniqueIds: [],
|
|
255
|
+
pageSize: 10,
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
jsonSchema: {},
|
|
260
|
+
}
|
|
261
|
+
const payloadDef = parsePayloadBlocksJson({
|
|
262
|
+
title: 'Ask',
|
|
263
|
+
blocks: [
|
|
264
|
+
{
|
|
265
|
+
id: 'p1',
|
|
266
|
+
type: 'case_multiselect',
|
|
267
|
+
name: 'selected_cases',
|
|
268
|
+
label: 'Ask Cases',
|
|
269
|
+
caseMinCount: 1,
|
|
270
|
+
caseMaxCount: 3,
|
|
271
|
+
caseFilter: {
|
|
272
|
+
agentKind: 'management',
|
|
273
|
+
agentUniqueId: 'agent-ask',
|
|
274
|
+
flowType: 'service',
|
|
275
|
+
flowUniqueIds: [],
|
|
276
|
+
pageSize: 20,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
})!
|
|
281
|
+
const result = intersectPayloadBlocksWithForm(payloadDef, form)
|
|
282
|
+
const block = result.matchedBlocks[0]
|
|
283
|
+
expect(block?.type).toBe('case_multiselect')
|
|
284
|
+
expect(block?.label).toBe('Ask Cases')
|
|
285
|
+
expect(block?.caseMaxCount).toBe(3)
|
|
286
|
+
expect(block?.caseFilter).toMatchObject({
|
|
287
|
+
agentUniqueId: 'agent-ask',
|
|
288
|
+
flowType: 'service',
|
|
289
|
+
pageSize: 20,
|
|
290
|
+
})
|
|
291
|
+
expect(block?.caseFilter?.category).toBeUndefined()
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
it('overlays ask resumeFilter over form resumeFilter', () => {
|
|
295
|
+
const form: FormSchema = {
|
|
296
|
+
title: 'Form',
|
|
297
|
+
description: '',
|
|
298
|
+
blocks: [
|
|
299
|
+
{
|
|
300
|
+
id: '1',
|
|
301
|
+
type: 'resume_multiselect',
|
|
302
|
+
name: 'partners',
|
|
303
|
+
label: 'Form Partners',
|
|
304
|
+
resumeFilter: {
|
|
305
|
+
names: ['Alice'],
|
|
306
|
+
agentUniqueIds: ['agent-form'],
|
|
307
|
+
resumeUniqueIds: [],
|
|
308
|
+
pageSize: 10,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
jsonSchema: {},
|
|
313
|
+
}
|
|
314
|
+
const payloadDef = parsePayloadBlocksJson({
|
|
315
|
+
title: 'Ask',
|
|
316
|
+
blocks: [
|
|
317
|
+
{
|
|
318
|
+
id: 'p1',
|
|
319
|
+
type: 'resume_multiselect',
|
|
320
|
+
name: 'partners',
|
|
321
|
+
label: '选择伙伴',
|
|
322
|
+
help: '请谨慎选择您的伙伴',
|
|
323
|
+
resumeEnableRefresh: true,
|
|
324
|
+
resumeFilter: {
|
|
325
|
+
names: [],
|
|
326
|
+
agentUniqueIds: [],
|
|
327
|
+
resumeUniqueIds: [],
|
|
328
|
+
pageSize: 20,
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
})!
|
|
333
|
+
const result = intersectPayloadBlocksWithForm(payloadDef, form)
|
|
334
|
+
const block = result.matchedBlocks[0]
|
|
335
|
+
expect(block?.label).toBe('选择伙伴')
|
|
336
|
+
expect(block?.help).toBe('请谨慎选择您的伙伴')
|
|
337
|
+
expect(block?.resumeFilter).toEqual({
|
|
338
|
+
names: [],
|
|
339
|
+
agentUniqueIds: [],
|
|
340
|
+
resumeUniqueIds: [],
|
|
341
|
+
pageSize: 20,
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
|
|
220
345
|
it('preserves payload layout blocks in renderBlocks on partial intersection', () => {
|
|
221
346
|
const partialPayload = parsePayloadBlocksJson({
|
|
222
347
|
title: 'Ask',
|
|
@@ -237,7 +362,7 @@ describe('intersectPayloadBlocksWithForm', () => {
|
|
|
237
362
|
])
|
|
238
363
|
expect(result.renderBlocks.map((b) => b.label)).toEqual([
|
|
239
364
|
'请填写以下信息',
|
|
240
|
-
'
|
|
365
|
+
'视频标题',
|
|
241
366
|
'提交后不可修改',
|
|
242
367
|
])
|
|
243
368
|
expect(result.renderBlocks.some((b) => b.type === 'heading' && b.label === '请填写以下信息')).toBe(
|