answer42 0.2.16__tar.gz → 0.2.18__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.
- {answer42-0.2.16 → answer42-0.2.18}/PKG-INFO +1 -1
- {answer42-0.2.16 → answer42-0.2.18}/pyproject.toml +1 -1
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form/Module.bsl +270 -50
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/assets/MCPTestManager.cf +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/server.py +35 -1
- {answer42-0.2.16 → answer42-0.2.18}/.gitignore +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/LICENSE +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/README.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/credentials.example.json +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/docs/agent-installation.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/docs/architecture.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/docs/assets/answer42-logo.png +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/docs/assets/platform42-logo.svg +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/docs/installation.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/scripts/build_cf.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/scripts/build_pages.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/scripts/e2e_stable.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/scripts/openclaw_mcp_autoreload.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/scripts/rag_cli.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/ConfigDumpInfo.xml +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/Configuration.xml +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260/Ext/Form.xml" +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager/Forms//320/244/320/276/321/200/320/274/320/260.xml" +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager.xml +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/Ext/ManagedApplicationModule.bsl +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/src/client_cf/ConfigDumpInfo.xml +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/client_cf/Configuration.xml +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/client_cf/Languages//320/240/321/203/321/201/321/201/320/272/320/270/320/271.xml" +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/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
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/__init__.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/assets/MCPTestClient.cf +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/assets/__init__.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/assets/skills/answer42/SKILL.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/assets/skills/answer42-rag/SKILL.md +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/bridge.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/credentials.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/os_support.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/platform.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/protocol.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/__init__.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/detect.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/model.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/parsers.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/service.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/rag/store.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/recorder.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/release_helper.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/runtime.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/src/mcp_1c/skill_installer.py +0 -0
- {answer42-0.2.16 → answer42-0.2.18}/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.
|
|
3
|
+
Version: 0.2.18
|
|
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>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "answer42"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.18"
|
|
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"
|
|
@@ -282,6 +282,10 @@
|
|
|
282
282
|
Возврат ОткрытьНавигационнуюСсылку(Параметры);
|
|
283
283
|
ИначеЕсли Метод = "current_element" Тогда
|
|
284
284
|
Возврат ТекущийЭлементФормы();
|
|
285
|
+
ИначеЕсли Метод = "field_dropdown_state" Тогда
|
|
286
|
+
Возврат СостояниеВыпадающегоСпискаПоляMCP(Параметры);
|
|
287
|
+
ИначеЕсли Метод = "field_dropdown_close" Тогда
|
|
288
|
+
Возврат ЗакрытьВыпадающийСписокПоляMCP(Параметры);
|
|
285
289
|
ИначеЕсли Метод = "table_current_row" Тогда
|
|
286
290
|
Возврат ТекущаяСтрокаТаблицы(Параметры);
|
|
287
291
|
ИначеЕсли Метод = "table_selected_rows" Тогда
|
|
@@ -434,15 +438,18 @@
|
|
|
434
438
|
КонецЕсли;
|
|
435
439
|
|
|
436
440
|
Выражение = СокрЛП(Код);
|
|
437
|
-
|
|
441
|
+
ЭтоВозврат = НРег(Лев(Выражение, 7)) = "возврат";
|
|
442
|
+
Если ЭтоВозврат Тогда
|
|
438
443
|
Выражение = СокрЛП(Сред(Выражение, 8));
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
444
|
+
Если Прав(Выражение, 1) = ";" Тогда
|
|
445
|
+
Выражение = Лев(Выражение, СтрДлина(Выражение) - 1);
|
|
446
|
+
КонецЕсли;
|
|
447
|
+
Результат = Вычислить(Выражение);
|
|
448
|
+
Возврат Новый Структура("value,type,presentation,executed_as", Результат, Строка(ТипЗнч(Результат)), Строка(Результат), "expression");
|
|
442
449
|
КонецЕсли;
|
|
443
450
|
|
|
444
|
-
|
|
445
|
-
Возврат Новый Структура("
|
|
451
|
+
Выполнить(Код);
|
|
452
|
+
Возврат Новый Структура("executed,executed_as", Истина, "statement");
|
|
446
453
|
КонецФункции
|
|
447
454
|
|
|
448
455
|
#КонецОбласти
|
|
@@ -3061,6 +3068,113 @@
|
|
|
3061
3068
|
Возврат Неопределено;
|
|
3062
3069
|
КонецФункции
|
|
3063
3070
|
|
|
3071
|
+
|
|
3072
|
+
|
|
3073
|
+
&НаКлиенте
|
|
3074
|
+
Функция СостояниеВыпадающегоСпискаПоляMCP(Параметры)
|
|
3075
|
+
ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
|
|
3076
|
+
ЗаголовокПоля = СвойствоСтруктуры(Параметры, "title", "");
|
|
3077
|
+
ИскатьПоЗаголовку = СвойствоСтруктуры(Параметры, "search_by_title", Ложь);
|
|
3078
|
+
МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 32);
|
|
3079
|
+
Таймаут = СвойствоСтруктуры(Параметры, "timeout", 60);
|
|
3080
|
+
Если ИскатьПоЗаголовку Тогда
|
|
3081
|
+
ЗаголовокПоля = ИмяПоля;
|
|
3082
|
+
ИмяПоля = "";
|
|
3083
|
+
КонецЕсли;
|
|
3084
|
+
АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3085
|
+
Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
|
|
3086
|
+
Если Поле = Неопределено Тогда
|
|
3087
|
+
ВызватьИсключение "Поле не найдено: " + ?(ПустаяСтрока(ИмяПоля), ЗаголовокПоля, ИмяПоля);
|
|
3088
|
+
КонецЕсли;
|
|
3089
|
+
Открыт = ОткрытВыпадающийСписокПоляMCP(Поле);
|
|
3090
|
+
Сформирован = Ложь;
|
|
3091
|
+
ПредставленияСтрокой = Новый Массив;
|
|
3092
|
+
Если Открыт Тогда
|
|
3093
|
+
Попытка
|
|
3094
|
+
Сформирован = Поле.ОжидатьФормированияВыпадающегоСписка(Таймаут);
|
|
3095
|
+
Исключение
|
|
3096
|
+
КонецПопытки;
|
|
3097
|
+
Попытка
|
|
3098
|
+
Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
|
|
3099
|
+
Для Каждого Представление Из Представления Цикл
|
|
3100
|
+
ПредставленияСтрокой.Добавить(ПредставлениеВариантаСпискаВыбораMCP(Представление));
|
|
3101
|
+
КонецЦикла;
|
|
3102
|
+
Исключение
|
|
3103
|
+
КонецПопытки;
|
|
3104
|
+
КонецЕсли;
|
|
3105
|
+
Возврат Новый Структура("field,opened,formed,count,items,value", ?(ПустаяСтрока(ИмяПоля), ЗаголовокПоля, ИмяПоля), Открыт, Сформирован, ПредставленияСтрокой.Количество(), ПредставленияСтрокой, ПредставлениеДанныхПоля(Поле));
|
|
3106
|
+
КонецФункции
|
|
3107
|
+
|
|
3108
|
+
&НаКлиенте
|
|
3109
|
+
Функция ЗакрытьВыпадающийСписокПоляMCP(Параметры)
|
|
3110
|
+
ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
|
|
3111
|
+
ЗаголовокПоля = СвойствоСтруктуры(Параметры, "title", "");
|
|
3112
|
+
ИскатьПоЗаголовку = СвойствоСтруктуры(Параметры, "search_by_title", Ложь);
|
|
3113
|
+
МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 32);
|
|
3114
|
+
Если ИскатьПоЗаголовку Тогда
|
|
3115
|
+
ЗаголовокПоля = ИмяПоля;
|
|
3116
|
+
ИмяПоля = "";
|
|
3117
|
+
КонецЕсли;
|
|
3118
|
+
АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3119
|
+
Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
|
|
3120
|
+
Если Поле = Неопределено Тогда
|
|
3121
|
+
ВызватьИсключение "Поле не найдено: " + ?(ПустаяСтрока(ИмяПоля), ЗаголовокПоля, ИмяПоля);
|
|
3122
|
+
КонецЕсли;
|
|
3123
|
+
БылОткрыт = ОткрытВыпадающийСписокПоляMCP(Поле);
|
|
3124
|
+
Если БылОткрыт Тогда
|
|
3125
|
+
Поле.ЗакрытьВыпадающийСписок();
|
|
3126
|
+
КонецЕсли;
|
|
3127
|
+
Возврат Новый Структура("field,closed,was_opened,value", ?(ПустаяСтрока(ИмяПоля), ЗаголовокПоля, ИмяПоля), БылОткрыт, БылОткрыт, ПредставлениеДанныхПоля(Поле));
|
|
3128
|
+
КонецФункции
|
|
3129
|
+
|
|
3130
|
+
|
|
3131
|
+
&НаКлиенте
|
|
3132
|
+
Функция ИндексРелевантногоВариантаСпискаВыбораMCP(Представления, ИскомоеПредставление)
|
|
3133
|
+
ИскомоеНРег = НРег(ИскомоеПредставление);
|
|
3134
|
+
Индекс = 0;
|
|
3135
|
+
ПервыйСодержащий = Неопределено;
|
|
3136
|
+
Для Каждого Представление Из Представления Цикл
|
|
3137
|
+
ТекстВарианта = ПредставлениеВариантаСпискаВыбораMCP(Представление);
|
|
3138
|
+
ОтображаемыйТекст = "";
|
|
3139
|
+
Если ТипЗнч(Представление) = Тип("Структура") Тогда
|
|
3140
|
+
Если Не Представление.Свойство("ОтображаемыйТекст", ОтображаемыйТекст) Тогда
|
|
3141
|
+
ОтображаемыйТекст = "";
|
|
3142
|
+
КонецЕсли;
|
|
3143
|
+
КонецЕсли;
|
|
3144
|
+
ТекстНРег = НРег(ТекстВарианта);
|
|
3145
|
+
ОтображаемыйНРег = НРег(ОтображаемыйТекст);
|
|
3146
|
+
Если ТекстНРег = ИскомоеНРег Или ОтображаемыйНРег = ИскомоеНРег Тогда
|
|
3147
|
+
Возврат Индекс;
|
|
3148
|
+
КонецЕсли;
|
|
3149
|
+
Если ПервыйСодержащий = Неопределено Тогда
|
|
3150
|
+
Если СтрНайти(ТекстНРег, ИскомоеНРег) > 0 Или СтрНайти(ОтображаемыйНРег, ИскомоеНРег) > 0 Тогда
|
|
3151
|
+
ПервыйСодержащий = Индекс;
|
|
3152
|
+
КонецЕсли;
|
|
3153
|
+
КонецЕсли;
|
|
3154
|
+
Индекс = Индекс + 1;
|
|
3155
|
+
КонецЦикла;
|
|
3156
|
+
Возврат ПервыйСодержащий;
|
|
3157
|
+
КонецФункции
|
|
3158
|
+
|
|
3159
|
+
&НаКлиенте
|
|
3160
|
+
Функция ИндексВариантаСпискаВыбораMCP(Представления, ИскомоеПредставление)
|
|
3161
|
+
Индекс = 0;
|
|
3162
|
+
Для Каждого Представление Из Представления Цикл
|
|
3163
|
+
ТекстВарианта = ПредставлениеВариантаСпискаВыбораMCP(Представление);
|
|
3164
|
+
ОтображаемыйТекст = "";
|
|
3165
|
+
Если ТипЗнч(Представление) = Тип("Структура") Тогда
|
|
3166
|
+
Если Не Представление.Свойство("ОтображаемыйТекст", ОтображаемыйТекст) Тогда
|
|
3167
|
+
ОтображаемыйТекст = "";
|
|
3168
|
+
КонецЕсли;
|
|
3169
|
+
КонецЕсли;
|
|
3170
|
+
Если ТекстВарианта = ИскомоеПредставление Или ОтображаемыйТекст = ИскомоеПредставление Тогда
|
|
3171
|
+
Возврат Индекс;
|
|
3172
|
+
КонецЕсли;
|
|
3173
|
+
Индекс = Индекс + 1;
|
|
3174
|
+
КонецЦикла;
|
|
3175
|
+
Возврат Неопределено;
|
|
3176
|
+
КонецФункции
|
|
3177
|
+
|
|
3064
3178
|
&НаКлиенте
|
|
3065
3179
|
Функция ПереключитьПолеMCP(Параметры)
|
|
3066
3180
|
Если ТестируемоеПриложение = Неопределено Тогда
|
|
@@ -3068,30 +3182,42 @@
|
|
|
3068
3182
|
КонецЕсли;
|
|
3069
3183
|
ИмяПоля = СвойствоСтруктуры(Параметры, "field_name", "");
|
|
3070
3184
|
Значение = СвойствоСтруктуры(Параметры, "value", Ложь);
|
|
3185
|
+
МаксимальнаяГлубина = СвойствоСтруктуры(Параметры, "max_depth", 20);
|
|
3071
3186
|
АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3072
|
-
Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, "", "", 0,
|
|
3187
|
+
Поле = НайтиОбъектРекурсивно(АктивноеОкно, ИмяПоля, "", "", 0, МаксимальнаяГлубина);
|
|
3073
3188
|
Если Поле = Неопределено Тогда
|
|
3074
3189
|
ВызватьИсключение "Поле не найдено: " + ИмяПоля;
|
|
3075
3190
|
КонецЕсли;
|
|
3076
3191
|
НужноДа = (Значение = Истина) Или (НРег(Строка(Значение)) = "да") Или (НРег(Строка(Значение)) = "true") Или (Строка(Значение) = "1");
|
|
3192
|
+
ТекущееПредставление = ПредставлениеДанныхПоля(Поле);
|
|
3193
|
+
СейчасДа = (НРег(Строка(ТекущееПредставление)) = "да") Или (НРег(Строка(ТекущееПредставление)) = "true") Или (Строка(ТекущееПредставление) = "1");
|
|
3194
|
+
Если НужноДа = СейчасДа Тогда
|
|
3195
|
+
Возврат Новый Структура("toggled,field,value,method", Истина, ИмяПоля, Значение, "ТекущееЗначение");
|
|
3196
|
+
КонецЕсли;
|
|
3077
3197
|
Попытка
|
|
3078
|
-
|
|
3079
|
-
Поле.УстановитьФлажок();
|
|
3080
|
-
Иначе
|
|
3081
|
-
Поле.СнятьФлажок();
|
|
3082
|
-
КонецЕсли;
|
|
3198
|
+
Поле.УстановитьОтметку();
|
|
3083
3199
|
Исключение
|
|
3084
|
-
|
|
3085
|
-
Попытка
|
|
3086
|
-
Поле.Активизировать();
|
|
3087
|
-
Поле.Выбрать();
|
|
3088
|
-
Исключение
|
|
3089
|
-
ВызватьИсключение "Не удалось переключить поле " + ИмяПоля + ": " + ОшибкаФлажок + "; " + ОписаниеОшибки();
|
|
3090
|
-
КонецПопытки;
|
|
3200
|
+
ВызватьИсключение "Не удалось переключить поле " + ИмяПоля + ": " + ОписаниеОшибки();
|
|
3091
3201
|
КонецПопытки;
|
|
3092
|
-
Возврат Новый Структура("toggled,field,value", Истина, ИмяПоля,
|
|
3202
|
+
Возврат Новый Структура("toggled,field,value,method", Истина, ИмяПоля, Значение, "УстановитьОтметку");
|
|
3093
3203
|
КонецФункции
|
|
3094
3204
|
|
|
3205
|
+
|
|
3206
|
+
&НаКлиенте
|
|
3207
|
+
Процедура ДобавитьДиагностикуМодальногоОкнаЕслиОткрылосьMCP(Результат, ЗаголовокОкнаДоДействия)
|
|
3208
|
+
Попытка
|
|
3209
|
+
АктивноеОкноПослеДействия = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3210
|
+
ЗаголовокОкнаПослеДействия = БезопасноеСвойство(АктивноеОкноПослеДействия, "Заголовок", "");
|
|
3211
|
+
НормализованныйЗаголовокДо = СтрЗаменить(ЗаголовокОкнаДоДействия, " *", "");
|
|
3212
|
+
НормализованныйЗаголовокПосле = СтрЗаменить(ЗаголовокОкнаПослеДействия, " *", "");
|
|
3213
|
+
Если Не ПустаяСтрока(ЗаголовокОкнаПослеДействия) И НормализованныйЗаголовокПосле <> НормализованныйЗаголовокДо Тогда
|
|
3214
|
+
Результат.Вставить("modal_opened", Истина);
|
|
3215
|
+
Результат.Вставить("modal_title", ЗаголовокОкнаПослеДействия);
|
|
3216
|
+
КонецЕсли;
|
|
3217
|
+
Исключение
|
|
3218
|
+
КонецПопытки;
|
|
3219
|
+
КонецПроцедуры
|
|
3220
|
+
|
|
3095
3221
|
&НаКлиенте
|
|
3096
3222
|
Функция УстановитьЗначениеПоля(Параметры)
|
|
3097
3223
|
Если ТестируемоеПриложение = Неопределено Тогда
|
|
@@ -3225,29 +3351,103 @@
|
|
|
3225
3351
|
// Для полей с выпадающим списком (ссылочные поля, поля выбора) платформа
|
|
3226
3352
|
// после ВвестиТекст() часто открывает dropdown с отфильтрованными вариантами.
|
|
3227
3353
|
// В этом случае выбираем первый вариант и возвращаем его представление.
|
|
3354
|
+
ТекстовыйВводВыполнен = Ложь;
|
|
3355
|
+
НеподтвержденноеПредставлениеПослеВвода = "";
|
|
3228
3356
|
Попытка
|
|
3357
|
+
ЗаголовокОкнаДоВвода = БезопасноеСвойство(АктивноеОкно, "Заголовок", "");
|
|
3229
3358
|
Поле.ВвестиТекст(Значение);
|
|
3359
|
+
ТекстовыйВводВыполнен = Истина;
|
|
3230
3360
|
Если ПустаяСтрока(Значение) Тогда
|
|
3231
3361
|
Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВвестиТекст");
|
|
3232
3362
|
КонецЕсли;
|
|
3233
3363
|
|
|
3234
|
-
//
|
|
3364
|
+
// ВвестиТекст() на web-клиенте может пересоздать/подменить объект поля.
|
|
3365
|
+
// Перед проверкой dropdown перечитываем поле из активного окна.
|
|
3366
|
+
АктивноеОкноПослеВвода = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3367
|
+
СвежееПолеПослеВвода = НайтиОбъектРекурсивно(АктивноеОкноПослеВвода, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
|
|
3368
|
+
Если СвежееПолеПослеВвода <> Неопределено Тогда
|
|
3369
|
+
Поле = СвежееПолеПослеВвода;
|
|
3370
|
+
КонецЕсли;
|
|
3371
|
+
|
|
3372
|
+
// Сначала проверяем, изменилось ли значение поля сразу после ввода.
|
|
3373
|
+
// Если да — возвращаем успех без ожидания dropdown.
|
|
3374
|
+
ПредставлениеСразуПослеВвода = ПредставлениеДанныхПоля(Поле);
|
|
3375
|
+
Если ПредставлениеСразуПослеВвода = Значение Или СтрНайти(ПредставлениеСразуПослеВвода, Значение) > 0 Тогда
|
|
3376
|
+
// Значение подтвердилось, но dropdown может открыться асинхронно
|
|
3377
|
+
// уже после этого. Коротко ждём и закрываем/выбираем, если открылся.
|
|
3378
|
+
НачалоПостОжидания = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
3379
|
+
Пока Не ОткрытВыпадающийСписокПоляMCP(Поле)
|
|
3380
|
+
И ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоПостОжидания < 1000 Цикл
|
|
3381
|
+
АктивноеОкноПослеВвода = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3382
|
+
СвежееПолеПослеВвода = НайтиОбъектРекурсивно(АктивноеОкноПослеВвода, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
|
|
3383
|
+
Если СвежееПолеПослеВвода <> Неопределено Тогда
|
|
3384
|
+
Поле = СвежееПолеПослеВвода;
|
|
3385
|
+
КонецЕсли;
|
|
3386
|
+
КонецЦикла;
|
|
3387
|
+
Если ОткрытВыпадающийСписокПоляMCP(Поле) Тогда
|
|
3388
|
+
Попытка
|
|
3389
|
+
Поле.ОжидатьФормированияВыпадающегоСписка(60);
|
|
3390
|
+
Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
|
|
3391
|
+
Если Представления.Количество() > 0 Тогда
|
|
3392
|
+
ИндексВыбора = ИндексРелевантногоВариантаСпискаВыбораMCP(Представления, Значение);
|
|
3393
|
+
Если ИндексВыбора <> Неопределено Тогда
|
|
3394
|
+
ПредставлениеВыбираемогоВарианта = ПредставлениеВариантаСпискаВыбораMCP(Представления[ИндексВыбора]);
|
|
3395
|
+
Попытка
|
|
3396
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(ПредставлениеВыбираемогоВарианта);
|
|
3397
|
+
Исключение
|
|
3398
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(ИндексВыбора);
|
|
3399
|
+
КонецПопытки;
|
|
3400
|
+
Иначе
|
|
3401
|
+
Поле.ЗакрытьВыпадающийСписок();
|
|
3402
|
+
КонецЕсли;
|
|
3403
|
+
Иначе
|
|
3404
|
+
Поле.ЗакрытьВыпадающийСписок();
|
|
3405
|
+
КонецЕсли;
|
|
3406
|
+
Исключение
|
|
3407
|
+
КонецПопытки;
|
|
3408
|
+
КонецЕсли;
|
|
3409
|
+
Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВвестиТекст");
|
|
3410
|
+
КонецЕсли;
|
|
3411
|
+
|
|
3412
|
+
// Значение не изменилось — ждём, не откроется ли dropdown асинхронно.
|
|
3235
3413
|
// Это характерно для ссылочных полей и полей с выбором из справочника.
|
|
3414
|
+
// На web-клиенте список может открыться асинхронно уже после возврата
|
|
3415
|
+
// ВвестиТекст(), поэтому коротко ждём именно факта открытия dropdown.
|
|
3416
|
+
НачалоОжиданияСписка = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
3417
|
+
Пока Не ОткрытВыпадающийСписокПоляMCP(Поле)
|
|
3418
|
+
И ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОжиданияСписка < 2000 Цикл
|
|
3419
|
+
АктивноеОкноПослеВвода = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
3420
|
+
СвежееПолеПослеВвода = НайтиОбъектРекурсивно(АктивноеОкноПослеВвода, ИмяПоля, ЗаголовокПоля, "", 0, МаксимальнаяГлубина);
|
|
3421
|
+
Если СвежееПолеПослеВвода <> Неопределено Тогда
|
|
3422
|
+
Поле = СвежееПолеПослеВвода;
|
|
3423
|
+
КонецЕсли;
|
|
3424
|
+
КонецЦикла;
|
|
3236
3425
|
Если ОткрытВыпадающийСписокПоляMCP(Поле) Тогда
|
|
3426
|
+
СписокСформирован = Ложь;
|
|
3237
3427
|
Попытка
|
|
3238
|
-
Поле.ОжидатьФормированияВыпадающегоСписка(
|
|
3428
|
+
СписокСформирован = Поле.ОжидатьФормированияВыпадающегоСписка(60);
|
|
3239
3429
|
Исключение
|
|
3240
3430
|
КонецПопытки;
|
|
3241
3431
|
Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
|
|
3242
3432
|
Если Представления.Количество() > 0 Тогда
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3433
|
+
ИндексВыбора = ИндексРелевантногоВариантаСпискаВыбораMCP(Представления, Значение);
|
|
3434
|
+
Если ИндексВыбора = Неопределено Тогда
|
|
3435
|
+
Поле.ЗакрытьВыпадающийСписок();
|
|
3436
|
+
ВызватьИсключение "Выпадающий список открыт, но релевантный вариант для значения " + Значение + " не найден";
|
|
3437
|
+
КонецЕсли;
|
|
3438
|
+
ПредставлениеВыбираемогоВарианта = ПредставлениеВариантаСпискаВыбораMCP(Представления[ИндексВыбора]);
|
|
3439
|
+
Попытка
|
|
3440
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(ПредставлениеВыбираемогоВарианта);
|
|
3441
|
+
Исключение
|
|
3442
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(ИндексВыбора);
|
|
3443
|
+
КонецПопытки;
|
|
3246
3444
|
ВыбранноеПредставление = ПредставлениеДанныхПоля(Поле);
|
|
3247
3445
|
Если ПустаяСтрока(ВыбранноеПредставление) Тогда
|
|
3248
3446
|
ВыбранноеПредставление = ПредставлениеВыбираемогоВарианта;
|
|
3249
3447
|
КонецЕсли;
|
|
3250
|
-
|
|
3448
|
+
РезультатВыбора = Новый Структура("set,field,value,method,selected,dropdown_formed,dropdown_index", Истина, ИмяПоля, Значение, "ВвестиТекст+ВыполнитьВыборИзСпискаВыбора", ВыбранноеПредставление, СписокСформирован, ИндексВыбора);
|
|
3449
|
+
ДобавитьДиагностикуМодальногоОкнаЕслиОткрылосьMCP(РезультатВыбора, ЗаголовокОкнаДоВвода);
|
|
3450
|
+
Возврат РезультатВыбора;
|
|
3251
3451
|
Иначе
|
|
3252
3452
|
// Список выбора пуст — просто закрываем dropdown.
|
|
3253
3453
|
Попытка
|
|
@@ -3255,22 +3455,18 @@
|
|
|
3255
3455
|
Исключение
|
|
3256
3456
|
КонецПопытки;
|
|
3257
3457
|
КонецЕсли;
|
|
3258
|
-
Иначе
|
|
3259
|
-
// Dropdown не открылся автоматически — пробуем открыть явно и выбрать.
|
|
3260
|
-
Попытка
|
|
3261
|
-
Поле.ОткрытьВыпадающийСписок();
|
|
3262
|
-
Поле.ОжидатьФормированияВыпадающегоСписка(10);
|
|
3263
|
-
Поле.ВыполнитьВыборИзСпискаВыбора(Значение);
|
|
3264
|
-
ВыбранноеПредставление = ПредставлениеДанныхПоля(Поле);
|
|
3265
|
-
Если ПустаяСтрока(ВыбранноеПредставление) Тогда
|
|
3266
|
-
ВыбранноеПредставление = Значение;
|
|
3267
|
-
КонецЕсли;
|
|
3268
|
-
Возврат Новый Структура("set,field,value,method,selected", Истина, ИмяПоля, Значение, "ВвестиТекст+ОткрытьВыпадающийСписок+ВыполнитьВыборИзСпискаВыбора", ВыбранноеПредставление);
|
|
3269
|
-
Исключение
|
|
3270
|
-
// Не удалось открыть/выбрать — продолжаем к циклу ожидания представления.
|
|
3271
|
-
КонецПопытки;
|
|
3272
3458
|
КонецЕсли;
|
|
3273
3459
|
|
|
3460
|
+
// Смещаем фокус на следующий элемент, чтобы сработали обработчики
|
|
3461
|
+
// ПриИзменении() и платформа обновила представление данных.
|
|
3462
|
+
Попытка
|
|
3463
|
+
ФормаПоля = НайтиРодительскуюФорму(Поле);
|
|
3464
|
+
Если ФормаПоля <> Неопределено Тогда
|
|
3465
|
+
ФормаПоля.ПерейтиКСледующемуЭлементу();
|
|
3466
|
+
КонецЕсли;
|
|
3467
|
+
Исключение
|
|
3468
|
+
КонецПопытки;
|
|
3469
|
+
|
|
3274
3470
|
НачалоОжиданияВвода = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
|
3275
3471
|
Пока ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОжиданияВвода < 2000 Цикл
|
|
3276
3472
|
АктивноеОкно = ТестируемоеПриложение.ПолучитьАктивноеОкно();
|
|
@@ -3283,11 +3479,18 @@
|
|
|
3283
3479
|
Возврат Новый Структура("set,field,value,method", Истина, ИмяПоля, Значение, "ВвестиТекст");
|
|
3284
3480
|
КонецЕсли;
|
|
3285
3481
|
КонецЦикла;
|
|
3286
|
-
|
|
3482
|
+
|
|
3483
|
+
// Текст введён, но представление не подтвердилось. Если dropdown сам
|
|
3484
|
+
// не открылся — не открываем его кодом, а возвращаем честную ошибку.
|
|
3485
|
+
НеподтвержденноеПредставлениеПослеВвода = ПредставлениеПослеВвода;
|
|
3287
3486
|
Исключение
|
|
3288
3487
|
Ошибки.Добавить("ВвестиТекст=" + ОписаниеОшибки());
|
|
3289
3488
|
КонецПопытки;
|
|
3290
3489
|
|
|
3490
|
+
Если ТекстовыйВводВыполнен Тогда
|
|
3491
|
+
ВызватьИсключение "Не удалось установить поле " + ИмяПоля + ": ВвестиТекст выполнен, но значение не подтвердилось; текущее представление: " + НеподтвержденноеПредставлениеПослеВвода;
|
|
3492
|
+
КонецЕсли;
|
|
3493
|
+
|
|
3291
3494
|
// Переключатели/радиокнопки и поля со списком выбора: после активации
|
|
3292
3495
|
// форма умеет выбирать значение из текущего открытого списка выбора.
|
|
3293
3496
|
Попытка
|
|
@@ -3339,10 +3542,23 @@
|
|
|
3339
3542
|
КонецПопытки;
|
|
3340
3543
|
|
|
3341
3544
|
Попытка
|
|
3545
|
+
ЗаголовокОкнаДоВыбора = БезопасноеСвойство(ТестируемоеПриложение.ПолучитьАктивноеОкно(), "Заголовок", "");
|
|
3342
3546
|
Поле.ОткрытьВыпадающийСписок();
|
|
3343
3547
|
Поле.ОжидатьФормированияВыпадающегоСписка(10);
|
|
3344
|
-
|
|
3345
|
-
|
|
3548
|
+
Представления = Поле.ПолучитьПредставлениеСпискаВыбора();
|
|
3549
|
+
ИндексВыбора = ИндексВариантаСпискаВыбораMCP(Представления, Значение);
|
|
3550
|
+
Если ИндексВыбора = Неопределено Тогда
|
|
3551
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(Значение);
|
|
3552
|
+
Иначе
|
|
3553
|
+
Поле.ВыполнитьВыборИзСпискаВыбора(ИндексВыбора);
|
|
3554
|
+
КонецЕсли;
|
|
3555
|
+
ВыбранноеПредставление = ПредставлениеДанныхПоля(Поле);
|
|
3556
|
+
Если ПустаяСтрока(ВыбранноеПредставление) Тогда
|
|
3557
|
+
ВыбранноеПредставление = Значение;
|
|
3558
|
+
КонецЕсли;
|
|
3559
|
+
РезультатВыбора = Новый Структура("set,field,value,method,selected", Истина, ИмяПоля, Значение, "ОткрытьВыпадающийСписок+ВыполнитьВыборИзСпискаВыбора", ВыбранноеПредставление);
|
|
3560
|
+
ДобавитьДиагностикуМодальногоОкнаЕслиОткрылосьMCP(РезультатВыбора, ЗаголовокОкнаДоВыбора);
|
|
3561
|
+
Возврат РезультатВыбора;
|
|
3346
3562
|
Исключение
|
|
3347
3563
|
Ошибки.Добавить("ОткрытьВыпадающийСписок=" + ОписаниеОшибки());
|
|
3348
3564
|
КонецПопытки;
|
|
@@ -3373,16 +3589,20 @@
|
|
|
3373
3589
|
&НаКлиенте
|
|
3374
3590
|
Функция ПредставлениеДанныхПоля(Поле)
|
|
3375
3591
|
Попытка
|
|
3376
|
-
|
|
3592
|
+
ПредставлениеДанных = Поле.ПолучитьПредставлениеДанных();
|
|
3593
|
+
Если Не ПустаяСтрока(ПредставлениеДанных) Тогда
|
|
3594
|
+
Возврат ПредставлениеДанных;
|
|
3595
|
+
КонецЕсли;
|
|
3596
|
+
Исключение
|
|
3597
|
+
КонецПопытки;
|
|
3598
|
+
|
|
3599
|
+
Попытка
|
|
3600
|
+
Возврат Поле.ПолучитьОтображаемыйТекст();
|
|
3377
3601
|
Исключение
|
|
3378
3602
|
Попытка
|
|
3379
|
-
Возврат
|
|
3603
|
+
Возврат Строка(БезопасноеСвойство(Поле, "Данные", ""));
|
|
3380
3604
|
Исключение
|
|
3381
|
-
|
|
3382
|
-
Возврат Строка(БезопасноеСвойство(Поле, "Данные", ""));
|
|
3383
|
-
Исключение
|
|
3384
|
-
Возврат "";
|
|
3385
|
-
КонецПопытки;
|
|
3605
|
+
Возврат "";
|
|
3386
3606
|
КонецПопытки;
|
|
3387
3607
|
КонецПопытки;
|
|
3388
3608
|
КонецФункции
|
|
Binary file
|
|
@@ -3126,6 +3126,39 @@ async def current_element(*,
|
|
|
3126
3126
|
return await _bridge_call_recorded(session_id, "current_element", {})
|
|
3127
3127
|
|
|
3128
3128
|
|
|
3129
|
+
@mcp.tool()
|
|
3130
|
+
async def field_dropdown_state(
|
|
3131
|
+
field_name: Annotated[str, "Field technical name or title"],
|
|
3132
|
+
search_by_title: Annotated[bool, "Search field by visible title"] = False,
|
|
3133
|
+
timeout: Annotated[int, "Wait timeout for dropdown formation"] = 60,
|
|
3134
|
+
max_depth: Annotated[int, "Maximum search depth"] = 32,
|
|
3135
|
+
*,
|
|
3136
|
+
session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
|
|
3137
|
+
) -> Any:
|
|
3138
|
+
"""Return whether a field dropdown is open and its visible choice items."""
|
|
3139
|
+
return await _bridge_call_recorded(
|
|
3140
|
+
session_id,
|
|
3141
|
+
"field_dropdown_state",
|
|
3142
|
+
{"field_name": field_name, "search_by_title": search_by_title, "timeout": timeout, "max_depth": max_depth},
|
|
3143
|
+
)
|
|
3144
|
+
|
|
3145
|
+
|
|
3146
|
+
@mcp.tool()
|
|
3147
|
+
async def field_dropdown_close(
|
|
3148
|
+
field_name: Annotated[str, "Field technical name or title"],
|
|
3149
|
+
search_by_title: Annotated[bool, "Search field by visible title"] = False,
|
|
3150
|
+
max_depth: Annotated[int, "Maximum search depth"] = 32,
|
|
3151
|
+
*,
|
|
3152
|
+
session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
|
|
3153
|
+
) -> Any:
|
|
3154
|
+
"""Close an open dropdown for a form field, if it is open."""
|
|
3155
|
+
return await _bridge_call_recorded(
|
|
3156
|
+
session_id,
|
|
3157
|
+
"field_dropdown_close",
|
|
3158
|
+
{"field_name": field_name, "search_by_title": search_by_title, "max_depth": max_depth},
|
|
3159
|
+
)
|
|
3160
|
+
|
|
3161
|
+
|
|
3129
3162
|
@mcp.tool()
|
|
3130
3163
|
async def table_current_row(
|
|
3131
3164
|
name: Annotated[str, "Table technical name"] = "",
|
|
@@ -3204,11 +3237,12 @@ async def tabular_document_save(
|
|
|
3204
3237
|
async def toggle_field(
|
|
3205
3238
|
field_name: Annotated[str, "Field technical name"],
|
|
3206
3239
|
value: Annotated[bool, "Desired checkbox value"] = False,
|
|
3240
|
+
max_depth: Annotated[int, "Max UI tree depth for nested fields"] = 20,
|
|
3207
3241
|
*,
|
|
3208
3242
|
session_id: Annotated[str, "Session id"] = DEFAULT_SESSION,
|
|
3209
3243
|
) -> Any:
|
|
3210
3244
|
"""Set a checkbox-like field using the 1C test client API."""
|
|
3211
|
-
return await _bridge_call_recorded(session_id, "toggle_field", {"field_name": field_name, "value": value})
|
|
3245
|
+
return await _bridge_call_recorded(session_id, "toggle_field", {"field_name": field_name, "value": value, "max_depth": max_depth})
|
|
3212
3246
|
|
|
3213
3247
|
|
|
3214
3248
|
@mcp.tool()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{answer42-0.2.16 → answer42-0.2.18}/src/cf/DataProcessors/MCPTestManager/Ext/ObjectModule.bsl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|