answer42 0.2.4__tar.gz → 0.2.6__tar.gz

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.
Files changed (59) hide show
  1. {answer42-0.2.4 → answer42-0.2.6}/PKG-INFO +1 -1
  2. {answer42-0.2.4 → answer42-0.2.6}/docs/architecture.md +23 -1
  3. {answer42-0.2.4 → answer42-0.2.6}/pyproject.toml +1 -1
  4. {answer42-0.2.4 → answer42-0.2.6}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl +476 -17
  5. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
  6. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +8 -0
  7. answer42-0.2.6/src/mcp_1c/rag/detect.py +101 -0
  8. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/rag/model.py +11 -0
  9. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/rag/parsers.py +27 -0
  10. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/rag/service.py +167 -8
  11. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/rag/store.py +12 -2
  12. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/runtime.py +1 -1
  13. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/server.py +756 -10
  14. answer42-0.2.4/src/mcp_1c/rag/detect.py +0 -23
  15. {answer42-0.2.4 → answer42-0.2.6}/.gitignore +0 -0
  16. {answer42-0.2.4 → answer42-0.2.6}/LICENSE +0 -0
  17. {answer42-0.2.4 → answer42-0.2.6}/README.md +0 -0
  18. {answer42-0.2.4 → answer42-0.2.6}/credentials.example.json +0 -0
  19. {answer42-0.2.4 → answer42-0.2.6}/docs/agent-installation.md +0 -0
  20. {answer42-0.2.4 → answer42-0.2.6}/docs/assets/answer42-logo.png +0 -0
  21. {answer42-0.2.4 → answer42-0.2.6}/docs/assets/platform42-logo.svg +0 -0
  22. {answer42-0.2.4 → answer42-0.2.6}/docs/installation.md +0 -0
  23. {answer42-0.2.4 → answer42-0.2.6}/scripts/build_cf.py +0 -0
  24. {answer42-0.2.4 → answer42-0.2.6}/scripts/build_pages.py +0 -0
  25. {answer42-0.2.4 → answer42-0.2.6}/scripts/e2e_stable.py +0 -0
  26. {answer42-0.2.4 → answer42-0.2.6}/scripts/openclaw_mcp_autoreload.py +0 -0
  27. {answer42-0.2.4 → answer42-0.2.6}/scripts/rag_cli.py +0 -0
  28. {answer42-0.2.4 → answer42-0.2.6}/src/cf/ConfigDumpInfo.xml +0 -0
  29. {answer42-0.2.4 → answer42-0.2.6}/src/cf/Configuration.xml +0 -0
  30. {answer42-0.2.4 → answer42-0.2.6}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
  31. {answer42-0.2.4 → answer42-0.2.6}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
  32. {answer42-0.2.4 → answer42-0.2.6}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
  33. {answer42-0.2.4 → answer42-0.2.6}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
  34. {answer42-0.2.4 → answer42-0.2.6}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
  35. {answer42-0.2.4 → answer42-0.2.6}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  36. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Catalogs//320/237/320/241_/320/222/320/273/320/260/320/264/320/265/320/273/320/265/321/206.xml" +0 -0
  37. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Catalogs//320/237/320/241_/320/241/320/277/321/200/320/260/320/262/320/276/321/207/320/275/320/270/320/2721.xml" +0 -0
  38. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/ConfigDumpInfo.xml +0 -0
  39. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Configuration.xml +0 -0
  40. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
  41. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ManagerModule.bsl" +0 -0
  42. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Ext/ObjectModule.bsl" +0 -0
  43. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205/Ext/Template.xml" +0 -0
  44. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262/Templates//320/236/321/201/320/275/320/276/320/262/320/275/320/260/321/217/320/241/321/205/320/265/320/274/320/260/320/232/320/276/320/274/320/277/320/276/320/275/320/276/320/262/320/272/320/270/320/224/320/260/320/275/320/275/321/213/321/205.xml" +0 -0
  45. {answer42-0.2.4 → answer42-0.2.6}/src/client_cf/Reports//320/237/320/241_/320/241/320/277/320/270/321/201/320/276/320/272/320/255/320/273/320/265/320/274/320/265/320/275/321/202/320/276/320/262.xml" +0 -0
  46. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/__init__.py +0 -0
  47. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
  48. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/assets/__init__.py +0 -0
  49. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
  50. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/bridge.py +0 -0
  51. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/credentials.py +0 -0
  52. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/os_support.py +0 -0
  53. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/platform.py +0 -0
  54. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/protocol.py +0 -0
  55. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/rag/__init__.py +0 -0
  56. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/recorder.py +0 -0
  57. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/release_helper.py +0 -0
  58. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/skill_installer.py +0 -0
  59. {answer42-0.2.4 → answer42-0.2.6}/src/mcp_1c/window_control.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: answer42
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API
5
5
  Author: Marvin (AI Assistant), 42Clouds, and contributors
6
6
  Author-email: "Kosolapov Stanislav (proDOOMman)" <prodoomman@gmail.com>
@@ -87,7 +87,7 @@ class SessionState:
87
87
  - динамические списки: `dynamic_list_available_fields`, `dynamic_list_apply_settings`, `dynamic_list_set_order`, `dynamic_list_output`, `dynamic_list_open_settings`, `dynamic_list_clear_settings`, `dynamic_list_open_form_settings`;
88
88
  - табличные документы: `tabular_documents`, `tabular_document_text`, `tabular_document_save`;
89
89
  - доказательная запись: `recording_start`, `recording_capture`, `recording_stop`;
90
- - RAG: `rag_source_add`, `rag_sources_list`, `rag_snapshot_create`, `rag_snapshots_list`, `rag_index_build`, `rag_lookup_object`, `rag_query`.
90
+ - RAG: `rag_source_add`, `rag_sources_add_from_directory`, `rag_source_roots_list`, `rag_sources_list`, `rag_available_configurations`, `rag_snapshot_create`, `rag_snapshots_list`, `rag_index_build`, `rag_lookup_object`, `rag_query`.
91
91
 
92
92
  ### `mcp_1c.bridge`
93
93
 
@@ -171,6 +171,24 @@ python3 scripts/rag_cli.py build --snapshot Configuration+Extension1
171
171
  python3 scripts/rag_cli.py lookup РегистрСведений.Регистр1 --snapshot Configuration+Extension1
172
172
  ```
173
173
 
174
+ ### Discovery roots
175
+
176
+ MCP tool `rag_sources_add_from_directory(path, watch=true)` scans a directory for
177
+ EDT/Designer XML configuration and extension roots, registers discovered sources,
178
+ and stores the directory in `source_roots`. Later calls to `rag_sources_list`,
179
+ `rag_source_roots_list` or `rag_available_configurations` can sync those roots and
180
+ pick up newly added source trees automatically. Discovery is bounded by
181
+ `max_depth` and skips noisy directories such as `.git`, `.venv`, `build`, `dist`
182
+ and `node_modules`.
183
+
184
+ `rag_available_configurations` returns grouped base/configuration sources,
185
+ extensions, other sources, snapshots, discovery roots and per-source indexed
186
+ object/chunk counts.
187
+
188
+ If a RAG lookup/query runs without a session snapshot, or the selected snapshot
189
+ has no indexed data, the result includes `rag_diagnostic.diagnostics[]` with a
190
+ machine-readable code and remediation message for the agent.
191
+
174
192
  ## Доказательная запись
175
193
 
176
194
  `recording_start()` включает запись. Каждый записываемый bridge-вызов сохраняет слайд с:
@@ -191,4 +209,8 @@ python3 scripts/rag_cli.py lookup РегистрСведений.Регистр1
191
209
  | `ONEC_MCP_REQUEST_TIMEOUT` | Таймаут запроса, сек | `60` |
192
210
  | `ONEC_MCP_DATA_DIR` | Рабочая директория | `/tmp/onec-mcp` |
193
211
  | `MCP_1C_RAG_DB` | Путь к RAG SQLite | `build/rag/onec-rag.sqlite` |
212
+ | `ONEC_MCP_DISABLE_RAG` | Отключить встроенный RAG (`1/true/yes/on`) | пусто |
213
+ | `ONEC_MCP_RAG_SOURCE_DIRS` | `:`/`;`-separated directories for startup RAG discovery/watch | пусто |
214
+ | `ONEC_MCP_RAG_SOURCE_PREFIX` | Prefix for auto-discovered source names | пусто |
215
+ | `ONEC_MCP_RAG_SOURCE_MAX_DEPTH` | Discovery depth for RAG source dirs | `4` |
194
216
  | `DISPLAY` | X11 display | `:99` |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "answer42"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
  description = "Answer42 — The Answer to Life, Universe, and 1C — UI Driver. MCP-powered 1C:Enterprise UI automation: click, fill, navigate, test, and introspect managed forms through the test-client API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -340,6 +340,8 @@
340
340
  Возврат ПредставлениеДанныхПоляMCP(Параметры);
341
341
  ИначеЕсли Метод = "field_tooltip" Тогда
342
342
  Возврат ПодсказкаПоляMCP(Параметры);
343
+ ИначеЕсли Метод = "field_dropdown_items" Тогда
344
+ Возврат ВариантыВыпадающегоСпискаПоляMCP(Параметры);
343
345
  ИначеЕсли Метод = "form_next_element" Тогда
344
346
  Возврат СледующийЭлементФормыMCP();
345
347
  ИначеЕсли Метод = "form_previous_element" Тогда
@@ -1051,7 +1053,8 @@
1051
1053
 
1052
1054
  ИскомоеИмя = ?(ИскатьПоЗаголовку, "", ИмяПоля);
1053
1055
  ИскомыйЗаголовок = ?(ИскатьПоЗаголовку, ИмяПоля, "");
1054
- Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИскомоеИмя, ИскомыйЗаголовок, "", 0, 8);
1056
+ МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 20);
1057
+ Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИскомоеИмя, ИскомыйЗаголовок, "", 0, МаксимальнаяГлубина);
1055
1058
 
1056
1059
  Если Поле = Неопределено Тогда
1057
1060
  Возврат Новый Структура("found,name,title", Ложь, ИмяПоля, "");
@@ -1063,6 +1066,16 @@
1063
1066
  Результат.Вставить("name", БезопасноеСвойство(Поле, "Имя", ""));
1064
1067
  Результат.Вставить("title", БезопасноеСвойство(Поле, "Заголовок", ""));
1065
1068
  Результат.Вставить("вид", Строка(ТипЗнч(Поле)));
1069
+ Попытка
1070
+ Результат.Вставить("field_kind", Строка(Поле.Вид));
1071
+ Исключение
1072
+ Результат.Вставить("field_kind_error", ОписаниеОшибки());
1073
+ КонецПопытки;
1074
+ Попытка
1075
+ Результат.Вставить("data_text", Поле.ПолучитьПредставлениеДанных());
1076
+ Исключение
1077
+ Результат.Вставить("data_text_error", ОписаниеОшибки());
1078
+ КонецПопытки;
1066
1079
  Результат.Вставить("visible", БезопасноеСвойство(Поле, "Видимость", Истина));
1067
1080
  Результат.Вставить("available", БезопасноеСвойство(Поле, "Доступность", Истина));
1068
1081
  Результат.Вставить("readonly", БезопасноеСвойство(Поле, "РежимТолькоПросмотр", Ложь));
@@ -1126,6 +1139,156 @@
1126
1139
  КонецПопытки;
1127
1140
  КонецФункции
1128
1141
 
1142
+ &НаКлиенте
1143
+ Функция ВариантыВыпадающегоСпискаПоляMCP(Параметры)
1144
+ Если ТестируемоеПриложение = Неопределено Тогда
1145
+ ВызватьИсключение "Тестируемое приложение не подключено.";
1146
+ КонецЕсли;
1147
+
1148
+ ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
1149
+ ИскатьПоЗаголовку = СвойствоСтруктуры(Параметры, "search_by_title", Ложь);
1150
+ Таймаут = СвойствоСтруктуры(Параметры, "timeout", 10);
1151
+ МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 3);
1152
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
1153
+
1154
+ ИскомоеИмя = ?(ИскатьПоЗаголовку, "", ИмяПоля);
1155
+ ИскомыйЗаголовок = ?(ИскатьПоЗаголовку, ИмяПоля, "");
1156
+ Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИскомоеИмя, ИскомыйЗаголовок, "тестируемоеполеформы", 0, МаксимальнаяГлубина);
1157
+
1158
+ Если Поле = Неопределено Тогда
1159
+ Возврат Новый Структура("found,name,title,opened,items,diagnostics", Ложь, ИмяПоля, "", Ложь, Новый Массив, Новый Массив);
1160
+ КонецЕсли;
1161
+
1162
+ Диагностика = Новый Массив;
1163
+ Варианты = Новый Массив;
1164
+ Открыт = Ложь;
1165
+ Источник = "choice_list_presentations";
1166
+
1167
+ Попытка
1168
+ // Это штатный интерактивный API test-client для списка выбора поля формы.
1169
+ // Для некоторых доступных визуально переключателей платформа запрещает интерактивные
1170
+ // действия, поэтому ниже есть неинтерактивный fallback через свойство СписокВыбора.
1171
+ Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
1172
+ ВариантыИзПредставленийСпискаВыбора(Представления, Варианты);
1173
+ Возврат Новый Структура("found,field,opened,items,diagnostics,source", Истина, ОбъектВСтруктуру(Поле, 0, 1), Ложь, Варианты, Диагностика, Источник);
1174
+ Исключение
1175
+ Диагностика.Добавить("choice_list_presentations_failed: " + ОписаниеОшибки());
1176
+ КонецПопытки;
1177
+
1178
+ Источник = "choice_list_property";
1179
+ Попытка
1180
+ СписокВыбора = БезопасноеСвойство(Поле, "СписокВыбора", Неопределено);
1181
+ Если СписокВыбора <> Неопределено Тогда
1182
+ ВариантыИзСпискаЗначений(СписокВыбора, Варианты);
1183
+ Если Варианты.Количество() > 0 Тогда
1184
+ Возврат Новый Структура("found,field,opened,items,diagnostics,source", Истина, ОбъектВСтруктуру(Поле, 0, 1), Ложь, Варианты, Диагностика, Источник);
1185
+ КонецЕсли;
1186
+ КонецЕсли;
1187
+ Исключение
1188
+ Диагностика.Добавить("choice_list_property_failed: " + ОписаниеОшибки());
1189
+ КонецПопытки;
1190
+
1191
+ Источник = "dropdown_children_fallback";
1192
+ Попытка
1193
+ Поле.Активизировать();
1194
+ Исключение
1195
+ Диагностика.Добавить("activate_failed: " + ОписаниеОшибки());
1196
+ КонецПопытки;
1197
+
1198
+ Попытка
1199
+ Поле.ОткрытьВыпадающийСписок();
1200
+ Исключение
1201
+ Возврат Новый Структура("found,field,opened,items,diagnostics,source,reason,error", Истина, ОбъектВСтруктуру(Поле, 0, 1), Ложь, Варианты, Диагностика, Источник, "open_dropdown_failed", ОписаниеОшибки());
1202
+ КонецПопытки;
1203
+
1204
+ Попытка
1205
+ Поле.ОжидатьФормированияВыпадающегоСписка(Таймаут);
1206
+ Исключение
1207
+ Диагностика.Добавить("wait_dropdown_failed: " + ОписаниеОшибки());
1208
+ КонецПопытки;
1209
+
1210
+ Попытка
1211
+ Открыт = Поле.ВыпадающийСписокОткрыт();
1212
+ Исключение
1213
+ Диагностика.Добавить("dropdown_open_state_failed: " + ОписаниеОшибки());
1214
+ КонецПопытки;
1215
+
1216
+ Попытка
1217
+ Для Каждого Подчиненный Из Поле.ПолучитьПодчиненныеОбъекты() Цикл
1218
+ Данные = ОбъектВСтруктуру(Подчиненный, 0, МаксимальнаяГлубина);
1219
+ Если Данные <> Неопределено Тогда
1220
+ Варианты.Добавить(Данные);
1221
+ КонецЕсли;
1222
+ КонецЦикла;
1223
+ Исключение
1224
+ Диагностика.Добавить("dropdown_children_failed: " + ОписаниеОшибки());
1225
+ КонецПопытки;
1226
+
1227
+ Попытка
1228
+ Поле.ЗакрытьВыпадающийСписок();
1229
+ Исключение
1230
+ Диагностика.Добавить("close_dropdown_failed: " + ОписаниеОшибки());
1231
+ КонецПопытки;
1232
+
1233
+ Возврат Новый Структура("found,field,opened,items,diagnostics,source", Истина, ОбъектВСтруктуру(Поле, 0, 1), Открыт, Варианты, Диагностика, Источник);
1234
+ КонецФункции
1235
+
1236
+ &НаКлиенте
1237
+ Процедура ВариантыИзПредставленийСпискаВыбора(Представления, Варианты)
1238
+ Для Каждого Представление Из Представления Цикл
1239
+ Вариант = Новый Структура;
1240
+ Если ТипЗнч(Представление) = Тип("Структура") Тогда
1241
+ Для Каждого Пара Из Представление Цикл
1242
+ Вариант.Вставить(Пара.Ключ, ?(Пара.Значение = Неопределено, "", Строка(Пара.Значение)));
1243
+ КонецЦикла;
1244
+ ЗаполнитьКлючиПредставленияВарианта(Вариант, Представление);
1245
+ Иначе
1246
+ Вариант.Вставить("presentation", Строка(Представление));
1247
+ Вариант.Вставить("text", Строка(Представление));
1248
+ КонецЕсли;
1249
+ Варианты.Добавить(Вариант);
1250
+ КонецЦикла;
1251
+ КонецПроцедуры
1252
+
1253
+ &НаКлиенте
1254
+ Процедура ВариантыИзСпискаЗначений(СписокВыбора, Варианты)
1255
+ Для Каждого ЭлементСписка Из СписокВыбора Цикл
1256
+ Вариант = Новый Структура;
1257
+ ЗначениеВарианта = БезопасноеСвойство(ЭлементСписка, "Значение", Неопределено);
1258
+ ПредставлениеВарианта = БезопасноеСвойство(ЭлементСписка, "Представление", "");
1259
+ Если ПустаяСтрока(ПредставлениеВарианта) Тогда
1260
+ ПредставлениеВарианта = БезопасноеСвойство(ЭлементСписка, "Текст", "");
1261
+ КонецЕсли;
1262
+ Если ПустаяСтрока(ПредставлениеВарианта) И ЗначениеВарианта <> Неопределено Тогда
1263
+ ПредставлениеВарианта = Строка(ЗначениеВарианта);
1264
+ КонецЕсли;
1265
+ Вариант.Вставить("presentation", ПредставлениеВарианта);
1266
+ Вариант.Вставить("text", ПредставлениеВарианта);
1267
+ Вариант.Вставить("value", ?(ЗначениеВарианта = Неопределено, "", Строка(ЗначениеВарианта)));
1268
+ Варианты.Добавить(Вариант);
1269
+ КонецЦикла;
1270
+ КонецПроцедуры
1271
+
1272
+ &НаКлиенте
1273
+ Процедура ЗаполнитьКлючиПредставленияВарианта(Вариант, Представление)
1274
+ Если Вариант.Свойство("ПредставлениеДанных") Тогда
1275
+ Вариант.Вставить("presentation", Вариант.ПредставлениеДанных);
1276
+ Вариант.Вставить("text", Вариант.ПредставлениеДанных);
1277
+ ИначеЕсли Вариант.Свойство("ОтображаемыйТекст") Тогда
1278
+ Вариант.Вставить("presentation", Вариант.ОтображаемыйТекст);
1279
+ Вариант.Вставить("text", Вариант.ОтображаемыйТекст);
1280
+ ИначеЕсли Вариант.Свойство("Представление") Тогда
1281
+ Вариант.Вставить("presentation", Вариант.Представление);
1282
+ Вариант.Вставить("text", Вариант.Представление);
1283
+ ИначеЕсли Вариант.Свойство("Значение") Тогда
1284
+ Вариант.Вставить("presentation", Вариант.Значение);
1285
+ Вариант.Вставить("text", Вариант.Значение);
1286
+ Иначе
1287
+ Вариант.Вставить("presentation", Строка(Представление));
1288
+ Вариант.Вставить("text", Строка(Представление));
1289
+ КонецЕсли;
1290
+ КонецПроцедуры
1291
+
1129
1292
  &НаКлиенте
1130
1293
  Функция СледующийЭлементФормыMCP()
1131
1294
  Если ТестируемоеПриложение = Неопределено Тогда
@@ -2214,7 +2377,7 @@
2214
2377
  Если Не ПустаяСтрока(ИскомыйЗаголовок) И НРег(СокрЛП(ИскомыйЗаголовок)) <> НормализованныйЗаголовок Тогда
2215
2378
  Возврат Ложь;
2216
2379
  КонецЕсли;
2217
- Если Не ПустаяСтрока(ИскомыйТип) И ТипОбъекта <> НРег(СокрЛП(ИскомыйТип)) Тогда
2380
+ Если Не ПустаяСтрока(ИскомыйТип) И ТипОбъекта <> НормализованноеИмяТипа(ИскомыйТип) Тогда
2218
2381
  Возврат Ложь;
2219
2382
  КонецЕсли;
2220
2383
  Возврат Истина;
@@ -2342,7 +2505,11 @@
2342
2505
  ЗаголовокТек = БезопасныйЗаголовок(Подчиненный);
2343
2506
  ТипТек = НормализованноеИмяТипа(Строка(ТипЗнч(Подчиненный)));
2344
2507
  Если ТипТек = "тестируемаякнопкакоманднойпанели" Или ТипТек = "тестируемаякнопкакомандногоинтерфейса" Или ТипТек = "тестируемаякнопкаформы" Тогда
2345
- Если ЭффективнаяДоступность И КнопкаСовпадает(ИмяТек, ЗаголовокТек, ИмяКнопки, ЗаголовокКнопки) Тогда
2508
+ // У кнопок на страницах мастеров родительская декоративная группа может быть
2509
+ // ТекущаяДоступность=Ложь, хотя сама кнопка в UI и test-client доступна.
2510
+ // Поэтому проверяем доступность самой кнопки, а не родителя.
2511
+ ДоступностьКнопки = БезопасноеЗначениеМетода(Подчиненный, "ТекущаяДоступность", БезопасноеСвойство(Подчиненный, "Доступность", Истина));
2512
+ Если ДоступностьКнопки И КнопкаСовпадает(ИмяТек, ЗаголовокТек, ИмяКнопки, ЗаголовокКнопки) Тогда
2346
2513
  Возврат Подчиненный;
2347
2514
  КонецЕсли;
2348
2515
  КонецЕсли;
@@ -2435,10 +2602,34 @@
2435
2602
  ВызватьИсключение "Тестируемое приложение не подключено.";
2436
2603
  КонецЕсли;
2437
2604
  АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
2605
+ ОшибкаАктивногоОкна = "";
2438
2606
  Попытка
2439
2607
  АктивноеОкно.ВыполнитьКоманду(НавигационнаяСсылка);
2440
2608
  Исключение
2441
- ВызватьИсключение "Не удалось перейти по навигационной ссылке " + НавигационнаяСсылка + ": " + ОписаниеОшибки();
2609
+ ОшибкаАктивногоОкна = ОписаниеОшибки();
2610
+ ОткрытоЧерезДругоеОкно = Ложь;
2611
+ ОшибкиОкон = Новый Массив;
2612
+ Для Каждого ТекущееОкно Из ОкнаТестируемогоПриложения() Цикл
2613
+ Если ТекущееОкно = АктивноеОкно Тогда
2614
+ Продолжить;
2615
+ КонецЕсли;
2616
+ Попытка
2617
+ Если Не БезопасноеСвойство(ТекущееОкно, "Доступность", Истина) Тогда
2618
+ Продолжить;
2619
+ КонецЕсли;
2620
+ Исключение
2621
+ КонецПопытки;
2622
+ Попытка
2623
+ ТекущееОкно.ВыполнитьКоманду(НавигационнаяСсылка);
2624
+ ОткрытоЧерезДругоеОкно = Истина;
2625
+ Прервать;
2626
+ Исключение
2627
+ ОшибкиОкон.Добавить(ОписаниеОшибки());
2628
+ КонецПопытки;
2629
+ КонецЦикла;
2630
+ Если Не ОткрытоЧерезДругоеОкно Тогда
2631
+ ВызватьИсключение "Не удалось перейти по навигационной ссылке " + НавигационнаяСсылка + ": " + ОшибкаАктивногоОкна;
2632
+ КонецЕсли;
2442
2633
  КонецПопытки;
2443
2634
  Диагностика = ПроверитьСостояниеКлиентаПослеШага();
2444
2635
  Если Диагностика.modal_is_error_window Тогда
@@ -2799,12 +2990,13 @@
2799
2990
  ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
2800
2991
  Значение = СвойствоСтруктуры(Параметры, "value", "");
2801
2992
  ИскатьПоЗаголовку = СвойствоСтруктуры(Параметры, "search_by_title", Ложь);
2993
+ МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 20);
2802
2994
  Если ПустаяСтрока(ИмяПоля) Тогда
2803
2995
  ВызватьИсключение "Не задано имя поля.";
2804
2996
  КонецЕсли;
2805
2997
  АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
2806
2998
  ЗаголовокПоля = ?(ИскатьПоЗаголовку, ИмяПоля, "");
2807
- Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, 8);
2999
+ Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
2808
3000
  Если Поле = Неопределено Тогда
2809
3001
  Попытка
2810
3002
  Поле = ТестируемоеПриложение.ПолучитьОбъект(Неопределено, ЗаголовокПоля, ИмяПоля, 1);
@@ -2815,27 +3007,293 @@
2815
3007
  Если Поле = Неопределено Тогда
2816
3008
  ВызватьИсключение "Поле не найдено: " + ИмяПоля;
2817
3009
  КонецЕсли;
3010
+
3011
+ Ошибки = Новый Массив;
3012
+
3013
+ ВидПоля = "";
3014
+ Попытка
3015
+ ВидПоля = Строка(Поле.Вид);
3016
+ Исключение
3017
+ ВидПоля = "";
3018
+ КонецПопытки;
3019
+
3020
+ Если ВидПоля = "Поле переключателя" Тогда
3021
+ ОшибкиПереключателя = Новый Массив;
3022
+ Для НомерПопытки = 1 По 20 Цикл
3023
+ // После смены варианта платформа может перестроить часть формы, поэтому
3024
+ // каждый раз перечитываем объект поля из актуального активного окна.
3025
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
3026
+ СвежееПоле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
3027
+ Если СвежееПоле <> Неопределено Тогда
3028
+ Поле = СвежееПоле;
3029
+ КонецЕсли;
3030
+ ТекущееПредставление = ПредставлениеДанныхПоля(Поле);
3031
+ Если ТекущееПредставление = Значение Тогда
3032
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ПолеПереключателя.ТекущееЗначение");
3033
+ КонецЕсли;
3034
+ ЗначениеДляВыбора = ЗначениеВариантаПереключателя(Поле, Значение);
3035
+ БылоИсключениеВыбора = Ложь;
3036
+ Попытка
3037
+ Поле.ВыбратьВариант(ЗначениеДляВыбора);
3038
+ Исключение
3039
+ // В 8.5 у некоторых полей-переключателей test-client может бросить
3040
+ // "Недоступный пользователю элемент...", но значение при этом уже
3041
+ // успевает перейти к следующему варианту. Поэтому не выходим сразу,
3042
+ // а перечитываем поле и проверяем состояние ниже.
3043
+ БылоИсключениеВыбора = Истина;
3044
+ Если ОшибкиПереключателя.Количество() < 3 Тогда
3045
+ ОшибкиПереключателя.Добавить(ОписаниеОшибки());
3046
+ КонецЕсли;
3047
+ КонецПопытки;
3048
+
3049
+ // ВыбратьВариант() на web-клиенте может менять значение асинхронно:
3050
+ // сразу после вызова/исключения представление еще старое, а через доли
3051
+ // секунды уже целевое. Коротко ждем именно состояния поля, не открытия
3052
+ // модальных окон и не пользовательского клика.
3053
+ НачалоОжиданияПереключателя = ТекущаяУниверсальнаяДатаВМиллисекундах();
3054
+ Пока ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОжиданияПереключателя < 1000 Цикл
3055
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
3056
+ СвежееПоле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
3057
+ Если СвежееПоле <> Неопределено Тогда
3058
+ Поле = СвежееПоле;
3059
+ КонецЕсли;
3060
+ ТекущееПредставление = ПредставлениеДанныхПоля(Поле);
3061
+ Если ТекущееПредставление = Значение Тогда
3062
+ МетодПереключателя = ?(БылоИсключениеВыбора, "ПолеПереключателя.ТекущееЗначениеПослеИсключения", "ПолеПереключателя.ВыбратьВариант");
3063
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, МетодПереключателя);
3064
+ КонецЕсли;
3065
+ КонецЦикла;
3066
+ КонецЦикла;
3067
+ НачалоОжиданияПереключателя = ТекущаяУниверсальнаяДатаВМиллисекундах();
3068
+ Пока ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОжиданияПереключателя < 2000 Цикл
3069
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
3070
+ СвежееПоле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
3071
+ Если СвежееПоле <> Неопределено Тогда
3072
+ Поле = СвежееПоле;
3073
+ КонецЕсли;
3074
+ ТекущееПредставление = ПредставлениеДанныхПоля(Поле);
3075
+ Если ТекущееПредставление = Значение Тогда
3076
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ПолеПереключателя.ТекущееЗначениеПослеОжидания");
3077
+ КонецЕсли;
3078
+ КонецЦикла;
3079
+ Если ОшибкиПереключателя.Количество() > 0 Тогда
3080
+ Ошибки.Добавить("ПолеПереключателя.ВыбратьВариант=" + СтрСоединить(ОшибкиПереключателя, "; ") + "; целевое значение не выбрано, текущее значение: " + ТекущееПредставление);
3081
+ Иначе
3082
+ Ошибки.Добавить("ПолеПереключателя.ВыбратьВариант=Значение не выбрано после 20 переключений, текущее значение: " + ТекущееПредставление);
3083
+ КонецЕсли;
3084
+ КонецЕсли;
3085
+
3086
+ Если ВидПоля = "Поле флажка" Тогда
3087
+ Попытка
3088
+ ТекущееПредставление = Поле.ПолучитьПредставлениеДанных();
3089
+ Исключение
3090
+ Попытка
3091
+ ТекущееПредставление = Поле.ПолучитьОтображаемыйТекст();
3092
+ Исключение
3093
+ ТекущееПредставление = "";
3094
+ КонецПопытки;
3095
+ КонецПопытки;
3096
+ НужноДа = (Значение = Истина) Или (НРег(Строка(Значение)) = "да") Или (НРег(Строка(Значение)) = "true") Или (Строка(Значение) = "1");
3097
+ СейчасДа = (НРег(Строка(ТекущееПредставление)) = "да") Или (НРег(Строка(ТекущееПредставление)) = "true") Или (Строка(ТекущееПредставление) = "1");
3098
+ Если НужноДа <> СейчасДа Тогда
3099
+ Попытка
3100
+ Поле.УстановитьОтметку();
3101
+ Исключение
3102
+ Ошибки.Добавить("ПолеФлажка.УстановитьОтметку=" + ОписаниеОшибки());
3103
+ КонецПопытки;
3104
+ КонецЕсли;
3105
+ Если Ошибки.Количество() = 0 Тогда
3106
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ПолеФлажка.УстановитьОтметку");
3107
+ КонецЕсли;
3108
+ КонецЕсли;
3109
+
3110
+ // Обычные поля ввода. На web-клиенте ВвестиТекст() может обновлять
3111
+ // представление асинхронно и/или пересоздавать объект поля. Поэтому после
3112
+ // ввода перечитываем поле из активного окна и коротко ждем фактическое
3113
+ // представление данных, прежде чем переходить к fallback-методам.
2818
3114
  Попытка
2819
3115
  Поле.ВвестиТекст(Значение);
3116
+ Если ПустаяСтрока(Значение) Тогда
3117
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВвестиТекст");
3118
+ КонецЕсли;
3119
+ НачалоОжиданияВвода = ТекущаяУниверсальнаяДатаВМиллисекундах();
3120
+ Пока ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОжиданияВвода < 2000 Цикл
3121
+ АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
3122
+ СвежееПоле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
3123
+ Если СвежееПоле <> Неопределено Тогда
3124
+ Поле = СвежееПоле;
3125
+ КонецЕсли;
3126
+ ПредставлениеПослеВвода = ПредставлениеДанныхПоля(Поле);
3127
+ Если ПредставлениеПослеВвода = Значение Или СтрНайти(ПредставлениеПослеВвода, Значение) > 0 Тогда
3128
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВвестиТекст");
3129
+ КонецЕсли;
3130
+ КонецЦикла;
3131
+ РезультатВвода = Новый Структура("set,field,value,method,verified,current_value", Истина, ИмяПоля, Значение, "ВвестиТекстБезПодтвержденияПредставления", Ложь, ПредставлениеПослеВвода);
3132
+ Возврат РезультатВвода;
3133
+ Исключение
3134
+ Ошибки.Добавить("ВвестиТекст=" + ОписаниеОшибки());
3135
+ КонецПопытки;
3136
+
3137
+ // Переключатели/радиокнопки и поля со списком выбора: после активации
3138
+ // форма умеет выбирать значение из текущего открытого списка выбора.
3139
+ Попытка
3140
+ Поле.Активизировать();
3141
+ ФормаПоля = НайтиРодительскуюФорму(Поле);
3142
+ Если ФормаПоля = Неопределено Тогда
3143
+ ВызватьИсключение "Родительская форма не найдена";
3144
+ КонецЕсли;
3145
+ ФормаПоля.ВыполнитьВыборИзСписка(Значение);
3146
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Форма.ВыполнитьВыборИзСписка");
3147
+ Исключение
3148
+ Ошибки.Добавить("Форма.ВыполнитьВыборИзСписка=" + ОписаниеОшибки());
3149
+ КонецПопытки;
3150
+
3151
+ Попытка
3152
+ Поле.Активизировать();
3153
+ ФормаПоля = НайтиРодительскуюФорму(Поле);
3154
+ Если ФормаПоля = Неопределено Тогда
3155
+ ВызватьИсключение "Родительская форма не найдена";
3156
+ КонецЕсли;
3157
+ ФормаПоля.ВыполнитьВыборИзМеню(Значение);
3158
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Форма.ВыполнитьВыборИзМеню");
3159
+ Исключение
3160
+ Ошибки.Добавить("Форма.ВыполнитьВыборИзМеню=" + ОписаниеОшибки());
3161
+ КонецПопытки;
3162
+
3163
+ Попытка
3164
+ Поле.Активизировать();
3165
+ Поле.ВыполнитьВыборИзСписка(Значение);
3166
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Поле.ВыполнитьВыборИзСписка");
3167
+ Исключение
3168
+ Ошибки.Добавить("Поле.ВыполнитьВыборИзСписка=" + ОписаниеОшибки());
3169
+ КонецПопытки;
3170
+
3171
+ Попытка
3172
+ Поле.Активизировать();
3173
+ Поле.ВыполнитьВыборИзМеню(Значение);
3174
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Поле.ВыполнитьВыборИзМеню");
3175
+ Исключение
3176
+ Ошибки.Добавить("Поле.ВыполнитьВыборИзМеню=" + ОписаниеОшибки());
3177
+ КонецПопытки;
3178
+
3179
+ // Поля со стандартным выпадающим списком.
3180
+ Попытка
3181
+ Поле.ВыполнитьВыборИзСпискаВыбора(Значение);
3182
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВыполнитьВыборИзСпискаВыбора");
3183
+ Исключение
3184
+ Ошибки.Добавить("ВыполнитьВыборИзСпискаВыбора=" + ОписаниеОшибки());
3185
+ КонецПопытки;
3186
+
3187
+ Попытка
3188
+ Поле.ОткрытьВыпадающийСписок();
3189
+ Поле.ОжидатьФормированияВыпадающегоСписка(10);
3190
+ Поле.ВыполнитьВыборИзСпискаВыбора(Значение);
3191
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ОткрытьВыпадающийСписок");
3192
+ Исключение
3193
+ Ошибки.Добавить("ОткрытьВыпадающийСписок=" + ОписаниеОшибки());
3194
+ КонецПопытки;
3195
+
3196
+ // Последние fallback-варианты для нестандартных тестируемых полей.
3197
+ Попытка
3198
+ Поле.Значение = Значение;
3199
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Значение");
3200
+ Исключение
3201
+ Ошибки.Добавить("Значение=" + ОписаниеОшибки());
3202
+ КонецПопытки;
3203
+ Попытка
3204
+ Поле.Текст = Значение;
3205
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "Текст");
3206
+ Исключение
3207
+ Ошибки.Добавить("Текст=" + ОписаниеОшибки());
3208
+ КонецПопытки;
3209
+ Попытка
3210
+ Поле.УстановитьЗначение(Значение);
3211
+ Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "УстановитьЗначение");
3212
+ Исключение
3213
+ Ошибки.Добавить("УстановитьЗначение=" + ОписаниеОшибки());
3214
+ КонецПопытки;
3215
+
3216
+ ВызватьИсключение "Не удалось установить поле " + ИмяПоля + ": " + СтрСоединить(Ошибки, "; ");
3217
+ КонецФункции
3218
+
3219
+ &НаКлиенте
3220
+ Функция ПредставлениеДанныхПоля(Поле)
3221
+ Попытка
3222
+ Возврат Поле.ПолучитьПредставлениеДанных();
2820
3223
  Исключение
2821
- ОшибкаВвестиТекст = ОписаниеОшибки();
2822
3224
  Попытка
2823
- Поле.Значение = Значение;
3225
+ Возврат Поле.ПолучитьОтображаемыйТекст();
2824
3226
  Исключение
2825
- ОшибкаЗначение = ОписаниеОшибки();
2826
3227
  Попытка
2827
- Поле.Текст = Значение;
3228
+ Возврат Строка(БезопасноеСвойство(Поле, "Данные", ""));
2828
3229
  Исключение
2829
- ОшибкаТекст = ОписаниеОшибки();
2830
- Попытка
2831
- Поле.УстановитьЗначение(Значение);
2832
- Исключение
2833
- ВызватьИсключение "Не удалось установить поле " + ИмяПоля + ": ВвестиТекст=" + ОшибкаВвестиТекст + "; Значение=" + ОшибкаЗначение + "; Текст=" + ОшибкаТекст + "; УстановитьЗначение=" + ОписаниеОшибки();
2834
- КонецПопытки;
3230
+ Возврат "";
2835
3231
  КонецПопытки;
2836
3232
  КонецПопытки;
2837
3233
  КонецПопытки;
2838
- Возврат Новый Структура("set,field,value", Истина, ИмяПоля, Значение);
3234
+ КонецФункции
3235
+
3236
+ &НаКлиенте
3237
+ Функция ЗначениеВариантаПереключателя(Поле, Представление)
3238
+ // ВыбратьВариант() ожидает значение элемента списка выбора, а не всегда
3239
+ // пользовательское представление. Для перечислений и других типизированных
3240
+ // значений строка "Основная" может не быть тем самым значением, хотя именно
3241
+ // она показывается пользователю.
3242
+ Попытка
3243
+ СписокВыбора = БезопасноеСвойство(Поле, "СписокВыбора", Неопределено);
3244
+ Если СписокВыбора <> Неопределено Тогда
3245
+ Для Каждого ЭлементСписка Из СписокВыбора Цикл
3246
+ ЗначениеВарианта = БезопасноеСвойство(ЭлементСписка, "Значение", Неопределено);
3247
+ ПредставлениеВарианта = БезопасноеСвойство(ЭлементСписка, "Представление", "");
3248
+ Если ПустаяСтрока(ПредставлениеВарианта) Тогда
3249
+ ПредставлениеВарианта = БезопасноеСвойство(ЭлементСписка, "Текст", "");
3250
+ КонецЕсли;
3251
+ Если ПустаяСтрока(ПредставлениеВарианта) И ЗначениеВарианта <> Неопределено Тогда
3252
+ ПредставлениеВарианта = Строка(ЗначениеВарианта);
3253
+ КонецЕсли;
3254
+ Если ПредставлениеВарианта = Представление Или Строка(ЗначениеВарианта) = Представление Тогда
3255
+ Возврат ЗначениеВарианта;
3256
+ КонецЕсли;
3257
+ КонецЦикла;
3258
+ КонецЕсли;
3259
+ Исключение
3260
+ КонецПопытки;
3261
+
3262
+ Попытка
3263
+ Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
3264
+ Для Каждого ВариантПредставления Из Представления Цикл
3265
+ Если ТипЗнч(ВариантПредставления) = Тип("Структура") Тогда
3266
+ ЗначениеВарианта = Неопределено;
3267
+ Если ВариантПредставления.Свойство("Значение", ЗначениеВарианта) Тогда
3268
+ ТекстВарианта = "";
3269
+ Если ВариантПредставления.Свойство("ПредставлениеДанных", ТекстВарианта) Или ВариантПредставления.Свойство("ОтображаемыйТекст", ТекстВарианта) Или ВариантПредставления.Свойство("Представление", ТекстВарианта) Тогда
3270
+ Если ТекстВарианта = Представление Тогда
3271
+ Возврат ЗначениеВарианта;
3272
+ КонецЕсли;
3273
+ КонецЕсли;
3274
+ КонецЕсли;
3275
+ КонецЕсли;
3276
+ КонецЦикла;
3277
+ Исключение
3278
+ КонецПопытки;
3279
+
3280
+ Возврат Представление;
3281
+ КонецФункции
3282
+
3283
+ &НаКлиенте
3284
+ Функция НайтиРодительскуюФорму(Объект)
3285
+ Текущий = Объект;
3286
+ Пока Текущий <> Неопределено Цикл
3287
+ Если НормализованноеИмяТипа(ТипЗнч(Текущий)) = "тестируемаяформа" Тогда
3288
+ Возврат Текущий;
3289
+ КонецЕсли;
3290
+ Попытка
3291
+ Текущий = Текущий.ПолучитьРодителя();
3292
+ Исключение
3293
+ Возврат Неопределено;
3294
+ КонецПопытки;
3295
+ КонецЦикла;
3296
+ Возврат Неопределено;
2839
3297
  КонецФункции
2840
3298
 
2841
3299
  &НаКлиенте
@@ -2845,8 +3303,9 @@
2845
3303
  КонецЕсли;
2846
3304
  ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
2847
3305
  ИскатьПоЗаголовку = СвойствоСтруктуры(Параметры, "search_by_title", Ложь);
3306
+ МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 20);
2848
3307
  АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
2849
- Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ?(ИскатьПоЗаголовку, ИмяПоля, ""), "", 0, 8);
3308
+ Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ?(ИскатьПоЗаголовку, ИмяПоля, ""), "", 0, МаксимальнаяГлубина);
2850
3309
  Если Поле = Неопределено Тогда
2851
3310
  ВызватьИсключение "Поле не найдено: " + ИмяПоля;
2852
3311
  КонецЕсли;