feat(web-test): fillFields/одиночный selectValue на полях-списках значений + фиксы

Модель может заполнять поля-списки одним значением или массивом через fillFields/
selectValue — раньше это виснет (DLB→форма «Выбор значений», safeClick по surface)
или throw «type dialog» (CB→«Список значений», ложный isTypeDialog). Статически
поле-список не отличить от обычного рефа → детекция поведенческая.

- Рефактор-шов: selectValuesMulti = открытие + dispatchMultiSurface(field,values,
  {formNum,isCloudDD,baseForm}); детекторы detectMultiSurface/isValueListSurface.
- Делегация на УЖЕ открытой форме (без переоткрытия/мигания), асимметрично по пути:
  DLB (fillReferenceField) — по «DLB открыл форму»; CB (одиночный selectValue, до
  isTypeDialog) — по Подбор/СнятьФлажки. Обычный реф (DLB→инлайн / форма «Выбрать»
  без этих кнопок) НЕ делегируется.
- fillFields: массив → selectValue(array); одиночное течёт в существующие
  hasSelect/hasPick ветки (фикс внутри них).
- Фикс clearPool для платформенного пула: Ctrl+A не выделяет все строки → цикл
  построчного удаления (кастомный пул с чекбоксами — через СнятьФлажки).

Регресс 25/25 (обычный реф Контрагент НЕ делегирован). Доп. кейсы в
22-multiselect-listfield. select-value v1.33, fill v1.20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-29 11:51:36 +03:00
parent 7b53f28644
commit 842e1d0de9
4 changed files with 140 additions and 33 deletions
@@ -9,7 +9,7 @@ export const timeout = 420000;
const sortq = a => [...a].sort();
export default async function({ navigateLink, selectValue, getFormState, wait, assert, step, log }) {
export default async function({ navigateLink, selectValue, fillFields, getFormState, wait, assert, step, log }) {
const fieldValue = async (name) => {
const fs = await getFormState();
@@ -83,4 +83,33 @@ export default async function({ navigateLink, selectValue, getFormState, wait, a
assert.deepEqual(sortq(r.selected.values), sortq(['ООО Север', 'ООО Юг']), 'оба контрагента подобраны');
assert.ok(!r.selected.notSelected, 'notSelected отсутствует');
});
// ── Делегирование через fillFields / одиночный selectValue (поведенческая детекция) ──
await step('fillFields одиночное на поле-списке (DLB) → делегирует, не виснет', async () => {
const f = await fillFields({ 'Через флажки': 'Альфа' });
log(`fillFields single: ${JSON.stringify(f.filled)}`);
assert.ok(f.filled?.[0]?.ok, 'значение проставлено без зависания');
assert.equal(await fieldValue('ЧерезФлажки'), 'Альфа', 'поле = Альфа');
});
await step('fillFields массивом на поле-списке → делегирует в мультивыбор', async () => {
const f = await fillFields({ 'Через флажки': ['Альфа', 'Бета'] });
log(`fillFields array: ${JSON.stringify(f.filled)}`);
assert.deepEqual(sortq(f.filled?.[0]?.values || []), sortq(['Альфа', 'Бета']), 'оба выбраны');
assert.equal(await fieldValue('ЧерезФлажки'), 'Альфа, Бета', 'поле = набор');
});
await step('fillFields одиночное на платформенном (CB) → не throw type-dialog (replace непустого пула)', async () => {
const f = await fillFields({ 'Без расширенного': 'АО Запад' });
log(`fillFields CB single: ${JSON.stringify(f.filled)}`);
assert.ok(f.filled?.[0]?.ok, 'значение проставлено (без ошибки type dialog)');
assert.equal(await fieldValue('СписокПлатформенный'), 'АО Запад', 'поле = АО Запад');
});
await step('одиночный selectValue на поле-списке → делегирует', async () => {
const r = await selectValue('Через флажки', 'Бета');
log(`selectValue single: ${JSON.stringify(r.selected)}`);
assert.deepEqual(r.selected.values, ['Бета'], 'одно значение выбрано');
assert.equal(await fieldValue('ЧерезФлажки'), 'Бета', 'поле = Бета');
});
}