[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `РазобратьURL`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция РазобратьURL(Знач URL)
Экспорт

	Схема = "";
	Путь = "";
	Аутентификация = Новый Структура("Пользователь, Пароль", "", "");
	Сервер = "";
	Порт = "";
	Фрагмент = "";

	ДопустимыеСхемы = СтрРазделить("http,https", ",");

	URLБезСхемы = URL;
	РазбитьСтрокуПоРазделителю(Схема, URLБезСхемы, "://");
	Если ДопустимыеСхемы.Найти(НРег(Схема)) <> Неопределено Тогда
		URL = URLБезСхемы;
	Иначе
		Схема = "";
	КонецЕсли;

	Результат = РазделитьПоПервомуНайденномуРазделителю(URL, СтрРазделить("/,?,#", ","));
	URL = Результат[0];
	Если ЗначениеЗаполнено(Результат[2]) Тогда
		Путь = Результат[2] + Результат[1];
	КонецЕсли;

	АутентификацияСтрока = "";
	РазбитьСтрокуПоРазделителю(АутентификацияСтрока, URL, "@");
	Если ЗначениеЗаполнено(АутентификацияСтрока) Тогда
		АутентификацияЧасти = СтрРазделить(АутентификацияСтрока, ":");
		Аутентификация.Пользователь = АутентификацияЧасти[0];
		Если АутентификацияЧасти.Количество() > 1 Тогда
			Аутентификация.Пароль = АутентификацияЧасти[1];
		КонецЕсли;
	КонецЕсли;

	// IPv6
	РазбитьСтрокуПоРазделителю(Сервер, URL, "]");
	Если ЗначениеЗаполнено(Сервер) Тогда
		Сервер = Сервер + "]";
	КонецЕсли;

	URL = СтрЗаменить(URL, "/", "");

	РазбитьСтрокуПоРазделителю(Порт, URL, ":", Истина);

	Если Не ЗначениеЗаполнено(Сервер) Тогда
    // TODO: допиши оставшуюся часть

[Assistant]
Функция РазобратьURL(Знач URL) Экспорт

	Схема = "";
	Путь = "";
	Аутентификация = Новый Структура("Пользователь, Пароль", "", "");
	Сервер = "";
	Порт = "";
	Фрагмент = "";

	ДопустимыеСхемы = СтрРазделить("http,https", ",");

	URLБезСхемы = URL;
	РазбитьСтрокуПоРазделителю(Схема, URLБезСхемы, "://");
	Если ДопустимыеСхемы.Найти(НРег(Схема)) <> Неопределено Тогда
		URL = URLБезСхемы;
	Иначе
		Схема = "";
	КонецЕсли;

	Результат = РазделитьПоПервомуНайденномуРазделителю(URL, СтрРазделить("/,?,#", ","));
	URL = Результат[0];
	Если ЗначениеЗаполнено(Результат[2]) Тогда
		Путь = Результат[2] + Результат[1];
	КонецЕсли;

	АутентификацияСтрока = "";
	РазбитьСтрокуПоРазделителю(АутентификацияСтрока, URL, "@");
	Если ЗначениеЗаполнено(АутентификацияСтрока) Тогда
		АутентификацияЧасти = СтрРазделить(АутентификацияСтрока, ":");
		Аутентификация.Пользователь = АутентификацияЧасти[0];
		Если АутентификацияЧасти.Количество() > 1 Тогда
			Аутентификация.Пароль = АутентификацияЧасти[1];
		КонецЕсли;
	КонецЕсли;

	// IPv6
	РазбитьСтрокуПоРазделителю(Сервер, URL, "]");
	Если ЗначениеЗаполнено(Сервер) Тогда
		Сервер = Сервер + "]";
	КонецЕсли;

	URL = СтрЗаменить(URL, "/", "");

	РазбитьСтрокуПоРазделителю(Порт, URL, ":", Истина);

	Если Не ЗначениеЗаполнено(Сервер) Тогда
		Сервер = URL;
	КонецЕсли;

	Если ЗначениеЗаполнено(Порт) Тогда
		Порт = Число(Порт);
	Иначе
		Порт = 0;
	КонецЕсли;

	РазбитьСтрокуПоРазделителю(Фрагмент, Путь, "#", Истина);

	ПараметрыЗапроса = ЗаполнитьПараметрыЗапроса(Путь);

	Если Не ЗначениеЗаполнено(Схема) Тогда
		Схема = "http";
	КонецЕсли;

	Если Не ЗначениеЗаполнено(Путь) Тогда
		Путь = "/";
	КонецЕсли;

	Результат = Новый Структура;
	Результат.Вставить("Схема", Схема);
	Результат.Вставить("Аутентификация", Аутентификация);
	Результат.Вставить("Сервер", Сервер);
	Результат.Вставить("Порт", Порт);
	Результат.Вставить("Путь", Путь);
	Результат.Вставить("ПараметрыЗапроса", ПараметрыЗапроса);
	Результат.Вставить("Фрагмент", Фрагмент);

	Возврат Результат;

КонецФункции

// Преобразование Объекта в JSON.
//
// Параметры:
//   Объект - Произвольный - данные, которые необходимо преобразовать в JSON.
//   ПараметрыПреобразования - Структура - кодировка текста JSON. Значение по умолчанию - utf-8.
//     * ФорматДатыJSON - ФорматДатыJSON - определяет формат сериализации дат JSON-объектов.
//     * ВариантЗаписиДатыJSON - ВариантЗаписиДатыJSON - определяет вариант записи даты в формате JSON.
//     * ИмяФункцииПреобразования - Строка - функция, которая вызывается для всех свойств,
//         тип которых не поддерживает автоматическую сериализацию в JSON.
//         Функция должна быть экспортируемая и иметь следующие параметры:
//           ** Свойство - Строка - свойство структуры данных, которое не может быть
//                автоматически сериализовано в JSON.
//           ** Значение - Строка - значение свойства структуры данных, которое
//                не может быть автоматически сериализовано в JSON.
//           ** ДополнительныеПараметры - Произвольный - в этом параметре будет передан
//                ДополнительныеПараметрыФункцииПреобразования.
//           ** Отказ - Булево - отменяет операцию записи свойства.
//         Возвращаемое значение функции:
//           Произвольный - результат преобразования.
//     * МодульФункцииПреобразования - Произвольный - модуль, в котором определена функция ИмяФункцииПреобразования.
//     * ДополнительныеПараметрыФункцииПреобразования - Произвольный - параметры, которые будут переданы
//                                                                     в функцию ИмяФункцииПреобразования.
//   ПараметрыЗаписи - Структура - параметры преобразования JSON:
//     * ПереносСтрок - ПереносСтрокJSON - определяет способ переноса строк,
//         который будет использован при записи данных JSON.
//     * СимволыОтступа - Строка - определяет символы отступа, используемые при записи данных JSON.
//     * ИспользоватьДвойныеКавычки - Булево - определяет, будут ли при записи имена свойств JSON
//         записываться в двойных кавычках.
//     * ЭкранированиеСимволов - ЭкранированиеСимволовJSON - определяет используемый способ экранирования (замены)
//         символов при записи данных JSON.
//     * ЭкранироватьУгловыеСкобки - Булево - определяет, будут ли при записи экранироваться символы "<" и ">".
//     * ЭкранироватьРазделителиСтрок - Булево - определяет, будут ли экранироваться разделители строк
//         U+2028 (line-separator) и U+2029 (page-separator).
//     * ЭкранироватьАмперсанд - Булево - определяет, будет ли при записи экранироваться символ амперсанда "&".
//     * ЭкранироватьОдинарныеКавычки - Булево - определяет, будут ли экранироваться одинарные кавычки.
//     * ЭкранироватьСлеш - Булево - определяет, будет ли экранироваться слеш (косая черта) при записи значения.
//
// Возвращаемое значение:
//   Строка - объект в формате JSON.
//


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `ВыбратьСценарий`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция ВыбратьСценарий(Запрос, ДополнительныеПараметры)
Экспорт

	ИмяСценария = ЗначениеПараметраИзЗапроса(Запрос, "name");
	Если НЕ ЗначениеЗаполнено(ИмяСценария) Тогда
		ТекстСообщения = Ванесса.Локализовать("Не указан обязательный параметр 'name'");
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);
	КонецЕсли;

	СценарииФичи = Ванесса.ПолучитьИменаСценариевПоТекущейФиче();

	Для Каждого ТекСценарий Из СценарииФичи Цикл
		Если НРег(ТекСценарий.Имя) = НРег(ИмяСценария) Тогда

			Ванесса.СделатьСтрокуДереваТекущейПоНомеруСтрокиФичи(ТекСценарий.НомерСтрокиВФиче);
			СтрокаДерева = Ванесса.СтрокаДереваПоНомеруСтрокиФичи(ТекСценарий.НомерСтрокиВФиче);
    // TODO: допиши оставшуюся часть

[Assistant]
Функция ВыбратьСценарий(Запрос, ДополнительныеПараметры) Экспорт

	ИмяСценария = ЗначениеПараметраИзЗапроса(Запрос, "name");
	Если НЕ ЗначениеЗаполнено(ИмяСценария) Тогда
		ТекстСообщения = Ванесса.Локализовать("Не указан обязательный параметр 'name'");
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);
	КонецЕсли;

	СценарииФичи = Ванесса.ПолучитьИменаСценариевПоТекущейФиче();

	Для Каждого ТекСценарий Из СценарииФичи Цикл
		Если НРег(ТекСценарий.Имя) = НРег(ИмяСценария) Тогда

			Ванесса.СделатьСтрокуДереваТекущейПоНомеруСтрокиФичи(ТекСценарий.НомерСтрокиВФиче);
			СтрокаДерева = Ванесса.СтрокаДереваПоНомеруСтрокиФичи(ТекСценарий.НомерСтрокиВФиче);
			Ванесса.МодульРедакторТекста().АктивизироватьСтрокуРедактораПоИдСтрокиИНомеруСтрокиФичи(СтрокаДерева.ИдСтроки, ТекСценарий.НомерСтрокиВФиче);

			Идентификатор = Запрос.Идентификатор;
			Ванесса.УстановитьИдентификаторЗадачиMCP(Идентификатор);
			ПодключитьОбработчикОжидания("ЗавершитьВыборСценария", 0.1, Истина);
			Возврат Неопределено;
		КонецЕсли;
	КонецЦикла;

	ТекстСообщения = Ванесса.Локализовать("Не найден сценарий:") + " " + ИмяСценария;
	Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);

КонецФункции

// Выбирает и делает шаг текущим. После этого можно вызывать выполнение с текущего шага
&НаКлиенте

Функция ВыбратьШаг(Запрос, ДополнительныеПараметры) Экспорт

	НомерСтроки = ЗначениеПараметраИзЗапроса(Запрос, "lineNumber");
	Если НЕ ЗначениеЗаполнено(НомерСтроки) Тогда
		ТекстСообщения = Ванесса.Локализовать("Не указан обязательный параметр 'lineNumber'");
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);
	КонецЕсли;

	ТекстОшибки = Неопределено;
	СделатьШагФичиТекущим(НомерСтроки, Запрос.Идентификатор, ТекстОшибки);
	Если ЗначениеЗаполнено(ТекстОшибки) Тогда
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("ACTION_FAILED", ТекстОшибки);
	КонецЕсли;
	ПодключитьОбработчикОжидания("ЗавершитьВыборШага", 0.1, Истина);

КонецФункции

// Вызывается при успешном завершении загрузки фичи/фич
&НаКлиенте

Процедура ОповеститьMCP_ОЗавершенииЗагрузкиФичи(ПутьКФайлу, Тип, ДопПараметрыВызоваMCP) Экспорт

	Если Тип = "СинтаксКонтроль" Тогда
		ЗавершитьПроверкуСинтаксиса(ПутьКФайлу);
	ИначеЕсли Тип = "ОткрытьФичаФайл" Тогда
		ЗавершитьОткрытиеФичаФайла(ПутьКФайлу);
	ИначеЕсли Тип = "ОткрытьЗагрузитьИлиПерезагрузитьФичаФайл" Тогда
		ЗавершитьОткрытьЗагрузитьИлиПерезагрузитьФичаФайл(ПутьКФайлу, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "ВыполнитьОдинШагВФичаФайле" Тогда
		ПродолжитьВыполнениеШагаВРедакторе(ПутьКФайлу, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "ВыполнитьСценарий" Тогда
		ПродолжитьВыполнитьСценарий1(ПутьКФайлу, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "ЗагрузитьФичуДляВыполненияСценария" Тогда
		// Проверяем, есть ли режим после загрузки (для reloadAndRunFromLine)
		Если ДопПараметрыВызоваMCP <> Неопределено И ДопПараметрыВызоваMCP.Свойство("РежимПослеЗагрузки") Тогда
			Если ДопПараметрыВызоваMCP.РежимПослеЗагрузки = "reloadAndRunFromLine" Тогда
				// Устанавливаем текущий шаг по номеру строки
				НомерСтроки = ДопПараметрыВызоваMCP.НомерСтроки;
				ТекстОшибки = Неопределено;
				СделатьШагФичиТекущим(НомерСтроки, Ванесса.ИдентификаторЗадачиMCP(), ТекстОшибки);
				Если ЗначениеЗаполнено(ТекстОшибки) Тогда
					МодульМсп_Сервер().ЗавершитьВызовИнструментаСОшибкой(Ванесса.ИдентификаторЗадачиMCP(), "ACTION_FAILED", ТекстОшибки);
					Возврат;
				КонецЕсли;
				ПодключитьОбработчикОжидания("ЗавершитьВыборШагаДляВыполненияСценарияСТекущегоШага", 0.1, Истина);
				Возврат;
			КонецЕсли;
		КонецЕсли;
		ПродолжитьВыполнитьСценарий2(ПутьКФайлу, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "ЗагрузитьФичаФайлИВыполнитьСценарии" Тогда
		Ванесса.КомандаВыполнитьСценарии();
	Иначе
		ТекстИсключения = Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("Не известный тип оповещения MCP после загрузки фичи <%1>"), Тип);
		ВызватьИсключение ТекстИсключения;
	КонецЕсли;

КонецПроцедуры

// Вызывается при успешном завершении выполнения одной строки фичи
&НаКлиенте

Функция ОповеститьMCP_ОУспешномЗавершенииВыполненияОднойСтрокиФичи(Тип, ДопПараметрыВызоваMCP) Экспорт

	Если Тип = "ВыполнитьОдинШагВФичаФайле" Тогда
		ЗавершитьУспешноеВыполнениеШагаВРедакторе(ДопПараметрыВызоваMCP);
	Иначе
		ТекстИсключения = Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("Не известный тип оповещения MCP после выполнения одной строки фичи <%1>"), Тип);
		ВызватьИсключение ТекстИсключения;
	КонецЕсли;

КонецФункции

// Вызывается при окончании выполнения сценариев
&НаКлиенте

Функция ОповеститьMCP_ОЗавершенииВыполненияСценариев(Тип, ДопПараметрыВызоваMCP) Экспорт

	Если Тип = "selected" Тогда
		ЗавершитьВыполненияСценария(Тип, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "all" Тогда
		ЗавершитьВыполненияСценария(Тип, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "reloadAndRun" Тогда
		ЗавершитьВыполненияСценария(Тип, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "reloadAndRunFromLine" Тогда
		ЗавершитьВыполненияСценария(Тип, ДопПараметрыВызоваMCP);
	ИначеЕсли Тип = "fromCurrentStep" Тогда
		ЗавершитьВыполненияСценария(Тип, ДопПараметрыВызоваMCP);
	Иначе
		ТекстИсключения = Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("Не известный тип оповещения MCP при завершении выполнения сценариев <%1>"), Тип);
		ВызватьИсключение ТекстИсключения;
	КонецЕсли;

КонецФункции

// Вызывается при ошибке при выполнении одной строки фичи
&НаКлиенте

Функция ОповеститьMCP_ОбОшибкеПриВыполненияОднойСтрокиФичи(Тип, ДопПараметрыВызоваMCP, РезультатПрохожденияШага) Экспорт

	Если Тип = "ВыполнитьОдинШагВФичаФайле" Тогда
		ЗавершитьВыполнениеШагаВРедактореСОшибкой(ДопПараметрыВызоваMCP, РезультатПрохожденияШага);
	Иначе
		ТекстИсключения = Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("Не известный тип оповещения MCP <%1>"), Тип);
		ВызватьИсключение ТекстИсключения;
	КонецЕсли;

КонецФункции

// Вызывается при ошибке выполнения выделенного сценария
&НаКлиенте

Функция ОповеститьMCP_ОбОшибкеВыполненияВыделенногоСценария(ДопПараметрыВызоваMCP, ТекстОшибки) Экспорт

	МодульМсп_Сервер().ЗавершитьВызовИнструментаУспешно(Ванесса.ПолучитьИдентификаторЗадачиMCP(), ТекстОшибки);
	Ванесса.УстановитьИдентификаторЗадачиMCP(Неопределено);

КонецФункции

// Вызывается при завершении выполнения шага строкой в MCPИнструментВыполнитьОдинШагТекстом
&НаКлиенте

Процедура ЗавершениеВыполнениеШагаИзСтроки() Экспорт
	МодульМсп_Сервер = МодульМсп_Сервер();
	ТекстСообщения = Ванесса.Локализовать("Шаг выполнен успешно");
	МодульМсп_Сервер.ЗавершитьВызовИнструментаУспешно(Ванесса.ПолучитьИдентификаторЗадачиMCP(), ТекстСообщения);
	Ванесса.УстановитьИдентификаторЗадачиMCP(Неопределено);
КонецПроцедуры

// Возврашает общий модуль из расширения MCP
&НаКлиенте

Функция МодульМсп_Сервер() Экспорт
	Возврат Вычислить("Мсп_Сервер");
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаКлиенте

Функция ИмяПровайдера()
	Возврат "VanessaAutomation";
КонецФункции

&НаКлиенте

Функция ЗначениеПараметраИзЗапроса(Запрос, ИмяПараметра)

	Значение = "";
	Запрос.Аргументы.Свойство(ИмяПараметра, Значение);
	Возврат Значение;

КонецФункции

&НаКлиенте

Процедура MCPИнструментПолучитьВсеШаги(ПараметрыСозданияMCP)

    Свойства = Новый Структура;
    //Свойства.Вставить("text", МодульМсп_СхемаПараметров.НовыйСвойствоСхемы("string", "Текст для обработки"));
    Поля = Новый Массив;
    //Поля.Добавить("text");
    Схема = ПараметрыСозданияMCP.МодульМсп_СхемаПараметров.НовыйСхемаОбъекта(Свойства, Поля);
    ПараметрыСозданияMCP.МодульМсп_Сервер.ЗарегистрироватьИнструмент(ПараметрыСозданияMCP.МодульМсп_Сервер.НовыйИнструмент(
        "get_all_steps_in_json_format",
        Ванесса.Локализовать("Возвращает все доступные шаги Vanessa Automation в формате массива json. Преполагается, что результат будет сохранен в файл и далее будет обрабатываться."),
        Схема,
        Новый ОписаниеОповещения("ВсеДоступныеШагиMCP", Вычислить("ЭтотОбъект"))),
		ИмяПровайдера());

КонецПроцедуры

&НаКлиенте


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `MCPОтправитьРезультатИнструментаСИзображением`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура MCPОтправитьРезультатИнструментаСИзображением(Текст, ДвоичныеДанныеИзображения, ДополнительныеПараметры, MimeТип = "image/png")
//Если MCPКомпонента = Неопределено Тогда
	//	Возврат;
	//КонецЕсли;

	Содержимое = Новый Массив;

	// Текстовая часть
	Если ЗначениеЗаполнено(Текст) Тогда
		ЭлементТекст = Новый Структура;
		ЭлементТекст.Вставить("type", "text");
		ЭлементТекст.Вставить("text", Текст);
		Содержимое.Добавить(ЭлементТекст);
	КонецЕсли;

	// Изображение в base64
	Если ДвоичныеДанныеИзображения <> Неопределено Тогда
		//Обработка картинки для уменьшения размера передаваемых данных
		Картинка = Новый Картинка(ДвоичныеДанныеИзображения);
		//Картинка.Записать("c:\temp\Исходная.png");

		// Получаем режим обработки изображения из дополнительных параметров
		ЦветовойРежим = "grayscale"; // по умолчанию
		Если ДополнительныеПараметры.Свойство("ЦветовойРежим") Тогда
			ЦветовойРежим = ДополнительныеПараметры.ЦветовойРежим;
		КонецЕсли;

		ИмяФайла = ДополнительныеПараметры.ИмяФайла;
		Если НЕ ЗначениеЗаполнено(ИмяФайла) Тогда
			ИмяФайла = ПолучитьИмяВременногоФайла("png");
		КонецЕсли;

		Если ЦветовойРежим = "grayscale" Тогда
			ОбработаннаяКартинка = ОбработаннаяКартинкаСервер(Картинка);
			ОбработаннаяКартинка.Записать(ИмяФайла);
		Иначе
			Картинка.Записать(ИмяФайла);
		КонецЕсли;

		//ОбработаннаяКартинка.Записать("c:\temp\Обработанная.png");
		//ДвоичныеДанныеИзображения = ОбработаннаяКартинка.ПолучитьДвоичныеДанные();

		//Base64Данные = Base64Строка(ДвоичныеДанныеИзображения);
		//Base64Данные = СтрЗаменить(Base64Данные, Символы.ВК, "");
		//Base64Данные = СтрЗаменить(Base64Данные, Символы.ПС, "");
		//ЭлементИзображение = Новый Структура;
		//ЭлементИзображение.Вставить("type", "image");
		//ЭлементИзображение.Вставить("data", Base64Данные);
		//ЭлементИзображение.Вставить("mimeType", MimeТип);
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура MCPОтправитьРезультатИнструментаСИзображением(Текст, ДвоичныеДанныеИзображения, ДополнительныеПараметры, MimeТип = "image/png")

	//Если MCPКомпонента = Неопределено Тогда
	//	Возврат;
	//КонецЕсли;

	Содержимое = Новый Массив;

	// Текстовая часть
	Если ЗначениеЗаполнено(Текст) Тогда
		ЭлементТекст = Новый Структура;
		ЭлементТекст.Вставить("type", "text");
		ЭлементТекст.Вставить("text", Текст);
		Содержимое.Добавить(ЭлементТекст);
	КонецЕсли;

	// Изображение в base64
	Если ДвоичныеДанныеИзображения <> Неопределено Тогда
		//Обработка картинки для уменьшения размера передаваемых данных
		Картинка = Новый Картинка(ДвоичныеДанныеИзображения);
		//Картинка.Записать("c:\temp\Исходная.png");

		// Получаем режим обработки изображения из дополнительных параметров
		ЦветовойРежим = "grayscale"; // по умолчанию
		Если ДополнительныеПараметры.Свойство("ЦветовойРежим") Тогда
			ЦветовойРежим = ДополнительныеПараметры.ЦветовойРежим;
		КонецЕсли;

		ИмяФайла = ДополнительныеПараметры.ИмяФайла;
		Если НЕ ЗначениеЗаполнено(ИмяФайла) Тогда
			ИмяФайла = ПолучитьИмяВременногоФайла("png");
		КонецЕсли;

		Если ЦветовойРежим = "grayscale" Тогда
			ОбработаннаяКартинка = ОбработаннаяКартинкаСервер(Картинка);
			ОбработаннаяКартинка.Записать(ИмяФайла);
		Иначе
			Картинка.Записать(ИмяФайла);
		КонецЕсли;

		//ОбработаннаяКартинка.Записать("c:\temp\Обработанная.png");
		//ДвоичныеДанныеИзображения = ОбработаннаяКартинка.ПолучитьДвоичныеДанные();

		//Base64Данные = Base64Строка(ДвоичныеДанныеИзображения);
		//Base64Данные = СтрЗаменить(Base64Данные, Символы.ВК, "");
		//Base64Данные = СтрЗаменить(Base64Данные, Символы.ПС, "");
		//ЭлементИзображение = Новый Структура;
		//ЭлементИзображение.Вставить("type", "image");
		//ЭлементИзображение.Вставить("data", Base64Данные);
		//ЭлементИзображение.Вставить("mimeType", MimeТип);
		//Содержимое.Добавить(ЭлементИзображение);

		ТекстСообщения = Ванесса.Локализовать("Скриншот окна записан в файл:") + " " + ИмяФайла;
		МодульМсп_Сервер().ЗавершитьВызовИнструментаУспешно(Ванесса.ПолучитьИдентификаторЗадачиMCP(), ТекстСообщения);
		Ванесса.УстановитьИдентификаторЗадачиMCP(Неопределено);
		Возврат;
	Иначе
		ТекстСообщения = Ванесса.Локализовать("Не вышло получить скриншот окна.");
		МодульМсп_Сервер().ЗавершитьВызовИнструментаСОшибкой(Ванесса.ИдентификаторЗадачиMCP(), "ACTION_FAILED", ТекстСообщения);
		Возврат;
	КонецЕсли;

	//ТелоРезультата = Новый Структура;
	//ТелоРезультата.Вставить("content", Содержимое);
	//
	//Ответ = Новый Структура;
	//Ответ.Вставить("id", Ванесса.ПолучитьИдентификаторЗадачиMCP());
	//
	//ЗаписьJSON = Новый ЗаписьJSON;
	//ЗаписьJSON.УстановитьСтроку();
	//ЗаписатьJSON(ЗаписьJSON, ТелоРезультата);
	//Ответ.Вставить("body", ЗаписьJSON.Закрыть());
	//
	//ЗаписьJSON = Новый ЗаписьJSON;
	//ЗаписьJSON.УстановитьСтроку();
	//ЗаписатьJSON(ЗаписьJSON, Ответ);
	//
	//Результат = ЗаписьJSON.Закрыть();

	//MCPКомпонента.НачатьВызовОтправитьОтвет(
	//	Новый ОписаниеОповещения("MCPПустойОбработчик", ЭтаФорма),
	//	ЗаписьJSON.Закрыть());

КонецПроцедуры

&НаСервереБезКонтекста

Функция ОбработаннаяКартинкаСервер(Картинка)

	ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(Картинка);
	ОбрабатываемаяКартинка.УстановитьФормат(ФорматКартинки.PNG);
	ОбрабатываемаяКартинка.УстановитьГлубинуЦвета(ГлубинаЦвета.БитНаПиксел8);
	ОбрабатываемаяКартинка.ПреобразоватьВОттенкиСерого();

	Возврат ОбрабатываемаяКартинка.ПолучитьКартинку();
КонецФункции

&НаКлиенте

Функция ЗначениеИзСтруктуры(Структура, Ключ)
	Если Структура.Свойство(Ключ) Тогда
		Возврат Структура[Ключ];
	КонецЕсли;

	Возврат Неопределено;
КонецФункции

&НаКлиенте

Процедура ЗавершитьВыборСценария()
	МодульМсп_Сервер().ЗавершитьВызовИнструментаУспешно(Ванесса.ПолучитьИдентификаторЗадачиMCP(), Ванесса.Локализовать("Сценарий сделан текущим. Теперь при выполнении текущего сценария будет выполнен этот сценарий."));
	Ванесса.УстановитьИдентификаторЗадачиMCP(Неопределено);
КонецПроцедуры

&НаКлиенте

Процедура ЗавершитьВыборШага()
	МодульМсп_Сервер().ЗавершитьВызовИнструментаУспешно(Ванесса.ПолучитьИдентификаторЗадачиMCP(), Ванесса.Локализовать("Шаг сделан текущим. Теперь можно запустить сценарий с текущего шага."));
	Ванесса.УстановитьИдентификаторЗадачиMCP(Неопределено);
КонецПроцедуры

&НаКлиенте

Процедура ЗавершитьВыборШагаДляВыполненияСценарияСТекущегоШага()
	Ванесса.ВыполнитьДанныйСценарийСТекущегоШага();
КонецПроцедуры

&НаКлиенте

Функция ПолучитьСтрокуДляПоискаШагаПоСнипету(Снипет)

	Поз = Найти(Снипет, "(");
	Если Поз > 0 Тогда
		Возврат НРег(Лев(Снипет, Поз - 1));
	КонецЕсли;

	Возврат НРег(Снипет);

КонецФункции

&НаКлиенте

Функция ПолучитьСообщенияПользователюИзОкна(ПараметрОкно)

	CообщенияПользователю = Неопределено;
	Попытка
		CообщенияПользователю = ПараметрОкно.ПолучитьТекстыСообщенийПользователю();
	Исключение
	КонецПопытки;

	Возврат CообщенияПользователю;

КонецФункции

&НаСервере

Функция ПолныйТекстБазыЗнанийСервер()

	ОбъектНаСервере = РеквизитФормыВЗначение("Объект");
	Возврат ОбъектНаСервере.ПолучитьМакет("БазаЗнанийДляMCP").ПолучитьТекст();

КонецФункции

&НаКлиенте

Функция ДанныеИзБазыЗнанийКлиент(ФорматОтвета, НомерВопроса, СтрокаПоиска)

	Если ФорматОтвета = "all" Тогда
		Возврат глКешБазыЗнаний;
	ИначеЕсли ФорматОтвета = "short_info" Тогда
		Возврат КороткаяИнформацияОБазеЗнаний();
	ИначеЕсли ФорматОтвета = "questions_only" Тогда
		Возврат ТолькоВопросыИзБазыЗнанийСНомерами();
	ИначеЕсли ФорматОтвета = "one_question" Тогда
		Возврат ПолучитьОтветНаОдинВопрос(НомерВопроса);
	ИначеЕсли ФорматОтвета = "question_search" Тогда
		Возврат ПоискПоВопросам(СтрокаПоиска);
	ИначеЕсли ФорматОтвета = "answers_search" Тогда
		Возврат ПоискПоОтветам(СтрокаПоиска);
	КонецЕсли;

КонецФункции

&НаКлиенте

Функция КороткаяИнформацияОБазеЗнаний()

	Вопросы = ПолучитьМассивВопросов();
	КолВопросов = Вопросы.Количество();

	КоличествоСимволов = СтрДлина(глКешБазыЗнаний);

	Возврат Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("## Количество вопросов: %1, размер базы знаний в символах: %2"), XMLСтрока(КолВопросов), XMLСтрока(КоличествоСимволов));

КонецФункции

&НаКлиенте

Функция ТолькоВопросыИзБазыЗнанийСНомерами()

	Вопросы = ПолучитьМассивВопросов();
	КолВопросов = Вопросы.Количество();

	КоличествоСимволов = СтрДлина(глКешБазыЗнаний);

	Результат = Новый Массив;
	Результат.Добавить(Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("## Количество вопросов: %1, размер базы знаний в символах: %2"), XMLСтрока(КолВопросов), XMLСтрока(КоличествоСимволов)));
	Результат.Добавить("");
	Для Каждого ТекВопрос Из Вопросы Цикл
		Результат.Добавить("Вопрос №" + xmlСтрока(ТекВопрос.Номер));
		Результат.Добавить(ТекВопрос.Текст);
		Результат.Добавить("");
	КонецЦикла;

	Возврат Ванесса._СтрСоединить(Результат);

КонецФункции

&НаКлиенте

Функция ПолучитьОтветНаОдинВопрос(НомерВопроса)

	Если НомерВопроса = Неопределено ИЛИ НомерВопроса <= 0 Тогда
		ТекстСообщения = Ванесса.Локализовать("Некорректно указан параметр 'question_number'");
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);
	КонецЕсли;

	Вопросы = ПолучитьМассивВопросов();
	Если НомерВопроса > Вопросы.Количество() Тогда
		ТекстСообщения = Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("Не корректно указан параметр 'question_number'. Всего вопросов %1, а передано значение %2"), XMLСтрока(Вопросы.Количество()), XMLСтрока(НомерВопроса));
		Возврат МодульМсп_Сервер().ОшибкаИнструмента("INVALID_PARAMS", ТекстСообщения);
	КонецЕсли;

	ТекВопрос = Вопросы[НомерВопроса - 1];
	Результат = Новый Массив;
	Результат.Добавить(ТекВопрос.ТекстВопросаБезОбработки);
	Для Каждого Стр Из ТекВопрос.Ответ Цикл
		Результат.Добавить(Стр);
	КонецЦикла;
	Возврат Ванесса._СтрСоединить(Результат);

КонецФункции

&НаКлиенте


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ИмяФайла)
	Текст = Новый ЧтениеТекста;
	Попытка
		Текст.Открыть(ИмяФайла,"UTF-8",,, Ложь);
		Лог = Текст.Прочитать();
		Текст.Закрыть();

		Если Найти(Лог,"[error] Error caused by") > 0 Тогда
			ОстановитьSikuliXСервер();
			Ванесса.СброситьФлагЗапускаSikuliXServer();
			Возврат Истина;
		КонецЕсли;
	Исключение
		Ванесса.Отладка(ОписаниеОшибки());
	КонецПопытки;

	Возврат Ложь;
КонецФункции

&НаКлиенте

Функция ВыполнитьСкрипт(СтрокаКоманды, ЖдатьОкончания, ОписаниеОшибки,ДопПараметры) Экспорт
	ИмяУправляющиегоФайлаSikuliXСервер = Ванесса.ИмяУправляющиегоФайлаSikuliXСервер();
	Ванесса.УдалитьФайлыКомандаСистемы(ИмяУправляющиегоФайлаSikuliXСервер);

	ЗаписатьУправляющийJson(ИмяУправляющиегоФайлаSikuliXСервер,СтрокаКоманды);

	ИмяФайлаВыводаКонсолиSikuliXСервер = Ванесса.ИмяФайлаВыводаКонсолиSikuliXСервер();

	Если ЖдатьОкончания Тогда
	//ждём файла ответа
		КоличествоПопытокЧтенияОтвета = 20;
		Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
			Если ДопПараметры.Свойство("Таймаут") Тогда
				КоличествоПопытокЧтенияОтвета = Макс(КоличествоПопытокЧтенияОтвета,ДопПараметры.Таймаут);
			КонецЕсли;
		КонецЕсли;

		Ответ = Неопределено;
		ИмяФайлаОтветаSikuliXСевер = Ванесса.ИмяФайлаОтветаSikuliXСевер();
		Для СчетчикПопыток = 1 По КоличествоПопытокЧтенияОтвета Цикл
			Если Ванесса.ФайлСуществуетКомандаСистемы(ИмяФайлаОтветаSikuliXСевер) Тогда
				Ответ = ПрочитатьФайлОтвета(ИмяФайлаОтветаSikuliXСевер);
				Ванесса.УдалитьФайлыКомандаСистемы(ИмяФайлаОтветаSikuliXСевер);
				Прервать;
			КонецЕсли;

			Если ЕстьОшибкаВВыполненииСкрипта(ИмяФайлаВыводаКонсолиSikuliXСервер) Тогда
				Прервать;
			КонецЕсли;

			Ванесса.sleep(1);
		КонецЦикла;

		Если Ответ = Неопределено Тогда
			ТекстСообщения = Ванесса.ПолучитьТекстСообщенияПользователю("Не получилось дождаться выполнения SikuliX скрипта <%1>.");
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",СтрокаКоманды);
			ВыводКонсоли = ВыводКонсолиSikuliXСервер();
			Если ЗначениеЗаполнено(ВыводКонсоли) Тогда
				ТекстСообщения = ТекстСообщения + Символы.ПС + Символы.ПС + ВыводКонсоли;
			КонецЕсли;

			ВызватьИсключение ТекстСообщения;
		КонецЕсли;

		Если Нрег(Ответ) <> "success" Тогда
			ТекстСообщения = Ванесса.ПолучитьТекстСообщенияПользователю("Не получилось выполнить SikuliX скрипт <%1>.");
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",СтрокаКоманды);
			ВыводКонсоли = ВыводКонсолиSikuliXСервер();
			Если ЗначениеЗаполнено(ВыводКонсоли) Тогда
				ТекстСообщения = ТекстСообщения + Символы.ПС + Символы.ПС + ВыводКонсоли;
			КонецЕсли;

			ВызватьИсключение ТекстСообщения;
		КонецЕсли;
	КонецЕсли;

	Возврат 0;
КонецФункции

&НаКлиенте

Процедура ОстановитьSikuliXСервер(ДопПараметры = Неопределено) Экспорт
	ИмяУправляющиегоФайлаSikuliXСервер = Ванесса.ИмяУправляющиегоФайлаSikuliXСервер();
	ЗаписатьУправляющийJson(ИмяУправляющиегоФайлаSikuliXСервер,"","exit0");

	ЗаписьВЖР = Истина;
	Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
		Если ДопПараметры.Свойство("ПриЗакрытии") Тогда
			ЗаписьВЖР = Ложь;
		КонецЕсли;
	КонецЕсли;

	Если ЗаписьВЖР Тогда
		Ванесса.ЗаписатьЛогВЖРИнформация("SikuliXСевер.ОстановкаSikuliXСервера", "");
	КонецЕсли;
КонецПроцедуры

// Делает отключение модуля
&НаКлиенте

Функция ОтключениеМодуля() Экспорт

	Ванесса = Неопределено;

КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаКлиенте

Процедура ОчиститьКаталог(Каталог)
	Если НЕ Ванесса.ФайлСуществуетКомандаСистемы(Каталог) Тогда
		Возврат;
	КонецЕсли;

	СписокКаталогов = Новый СписокЗначений;
	СписокФайлов    = Новый СписокЗначений;
	Ванесса.НайтиФайлыКомандаСистемы(Каталог, СписокКаталогов, СписокФайлов, Истина);

	Для Каждого Файл Из СписокФайлов Цикл
		Попытка
			Ванесса.УдалитьФайлыКомандаСистемы(Файл.Значение.ПолноеИмя);
		Исключение
		КонецПопытки;
	КонецЦикла;

	СписокКаталогов = Новый СписокЗначений;
	СписокФайлов    = Новый СписокЗначений;
	Ванесса.НайтиФайлыКомандаСистемы(Каталог, СписокКаталогов, СписокФайлов, Истина);
	Для Каждого Файл Из СписокФайлов Цикл
		Попытка
			Ванесса.УдалитьФайлыКомандаСистемы(Файл.Значение.ПолноеИмя);
		Исключение
			ТекстСообщения = Ванесса.ПолучитьТекстСообщенияПользователю("Не получилось удалить файл %1");
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",Файл.Значение.ПолноеИмя);
			ВызватьИсключение ТекстСообщения;
		КонецПопытки;
	КонецЦикла;
КонецПроцедуры

&НаКлиенте

Функция ДанныеСкрипта(КаталогСкрипта,ОбщаяСекцияИмпорт)
	ФайлКаталогСкрипта = Новый Файл(КаталогСкрипта);
	ИмяСкрипта = ФайлКаталогСкрипта.ИмяБезРасширения;

	КартинкиСкрипта = Новый Массив;
	СписокКаталогов = Новый СписокЗначений;
	СписокФайлов    = Новый СписокЗначений;
	Ванесса.НайтиФайлыКомандаСистемы(КаталогСкрипта, СписокКаталогов, СписокФайлов, Ложь);
	Ванесса.ОставитьТолькоФайлыСРасширением(СписокФайлов,".png");

	Для Каждого Файл Из СписокФайлов Цикл
		ДанныеКартинки = Новый Структура;
		ДанныеКартинки.Вставить("ИмяФайла",Файл.Значение.Имя);
		ДанныеКартинки.Вставить("ПолноеИмя",СтрЗаменить(Файл.Значение.ПолноеИмя,"\","/"));
		КартинкиСкрипта.Добавить(ДанныеКартинки);
	КонецЦикла;

	ДанныеСкрипта = Новый Структура;

	НашлиФайл = Ложь;
	СписокКаталогов = Новый СписокЗначений;
	СписокФайлов    = Новый СписокЗначений;
	Ванесса.НайтиФайлыКомандаСистемы(КаталогСкрипта, СписокКаталогов, СписокФайлов, Ложь);
	Ванесса.ОставитьТолькоФайлыСРасширением(СписокФайлов,".py");

	Для Каждого Файл Из СписокФайлов Цикл
		Если НРег(Файл.Значение.ИмяБезРасширения) = НРег(ИмяСкрипта) Тогда
			НашлиФайл = Истина;

			ДанныеСкрипта.Вставить("ИмяСкрипта",ИмяСкрипта);
			СекцияИмпорт = Новый Массив;
			ДанныеСкрипта.Вставить("СекцияИмпорт",СекцияИмпорт);
			ТелоСкрипта = Новый Массив;
			ДанныеСкрипта.Вставить("ТелоСкрипта",ТелоСкрипта);

			Текст = Новый ЧтениеТекста;
			Текст.Открыть(Файл.Значение.ПолноеИмя,"UTF-8");

			Пока Истина Цикл
				Стр = Текст.ПрочитатьСтроку();
				Если Стр = Неопределено Тогда
					Прервать;
				КонецЕсли;

				Если Лев(Стр,6) = "import" Тогда
					Стр = СокрЛП(НРег(Стр));
					Если ОбщаяСекцияИмпорт.Найти(Стр) = Неопределено Тогда
						ОбщаяСекцияИмпорт.Добавить(Стр);
						Продолжить;
					КонецЕсли;
				ИначеЕсли Найти(НРег(Стр),".png") > 0 Тогда
					Для Каждого КартинкаСкрипта Из КартинкиСкрипта Цикл
						Стр = СтрЗаменить(Стр,КартинкаСкрипта.ИмяФайла,КартинкаСкрипта.ПолноеИмя);
					КонецЦикла;
				ИначеЕсли НРег(СокрЛП(Стр)) = "exit(0)" Тогда
					//надо заменить на пустую команду
					Стр = СтрЗаменить(НРег(Стр),"exit(0)","pass");
				ИначеЕсли НРег(СокрЛП(Стр)) = "exit(1)" Тогда
					//Пока решно вызывать исключение если оно описано в скрипте
					//КолПробелов = СтрДлина(Стр) - СтрДлина(СокрЛ(Стр));
					//Стр = Лев(Стр,КолПробелов) + "CallError(""" + ИмяСкрипта + """)";
				КонецЕсли;

				Стр = СтрЗаменить(Стр,"sys.argv[1]","sys_argv_1");
				Стр = СтрЗаменить(Стр,"sys.argv[2]","sys_argv_2");
				Стр = СтрЗаменить(Стр,"sys.argv[3]","sys_argv_3");
				Стр = СтрЗаменить(Стр,"sys.argv[4]","sys_argv_4");
				Стр = СтрЗаменить(Стр,"sys.argv[5]","sys_argv_5");

				ТелоСкрипта.Добавить(Стр);
			КонецЦикла;

			Текст.Закрыть();
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Если Не НашлиФайл Тогда
		ТекстСообщения = "Не найден файл <" + ИмяСкрипта + ".py> в каталоге <" + КаталогСкрипта + ">";
		Сообщить(ТекстСообщения);
		Возврат Неопределено;
	КонецЕсли;

	Возврат ДанныеСкрипта;
КонецФункции

&НаКлиенте

Функция ПрочитатьФайлОтвета(ИмяФайла)
	ЧтениеJSON = Вычислить("Новый ЧтениеJSON");
	ЧтениеJSON.ОткрытьФайл(ИмяФайла);
	СтруктураПараметров = Вычислить("ПрочитатьJSON(ЧтениеJSON)");
	ЧтениеJSON.Закрыть();
	Возврат СтруктураПараметров.Response;
КонецФункции

&НаКлиенте

[Assistant] Функция ЕстьОшибкаВВыполненииСкрипта(ИмяФайла)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `СоздатьFeatureReader`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция СоздатьFeatureReader(КаталогИнструментов, ДвДанныеvbFeatureReader, ВременноеИмяФайла)
Если Объект.ВерсияПоставки = "single" Тогда
		ОбъектСервер = РеквизитФормыВЗначение("Объект");
		Возврат ОбъектСервер;
	КонецЕсли;

	ФайлvbFeatureReader = Новый Файл(КаталогИнструментов + "\lib\FeatureReader\vbFeatureReader.epf");
	ВременноеИмяФайла = Неопределено;
	Если Не ФайлvbFeatureReader.Существует() Тогда
		ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
    // TODO: допиши оставшуюся часть

[Assistant]
Функция СоздатьFeatureReader(КаталогИнструментов, ДвДанныеvbFeatureReader, ВременноеИмяФайла)
	Если Объект.ВерсияПоставки = "single" Тогда
		ОбъектСервер = РеквизитФормыВЗначение("Объект");
		Возврат ОбъектСервер;
	КонецЕсли;

	ФайлvbFeatureReader = Новый Файл(КаталогИнструментов + "\lib\FeatureReader\vbFeatureReader.epf");
	ВременноеИмяФайла = Неопределено;
	Если Не ФайлvbFeatureReader.Существует() Тогда
		ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
		ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
		FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла, Ложь);
	Иначе
		FeatureReader = ВнешниеОбработки.Создать(ФайлvbFeatureReader.ПолноеИмя, Ложь);
	КонецЕсли;

	Возврат FeatureReader;
КонецФункции

#КонецОбласти

#Область РаботаСДеревомШагов

&НаСервере

Процедура ДобавитьТипыШагов(Дерево,Тип,ТаблицаПеревода)
	НайденныеСтрокиДерева = Дерево.Строки.НайтиСтроки(Новый Структура("ПолныйТипШага",Тип),Истина);
	Если НайденныеСтрокиДерева.Количество() = 0 Тогда
		ТекСтроки = Дерево.Строки;
		МассивТип = РазложитьСтрокуВМассивПодстрок(Тип,".");
		ПолныйТипШага = "";
		Для Каждого ПодТип Из МассивТип Цикл
			ЕстьПеревод = Ложь;

			Если ТаблицаПеревода <> Неопределено Тогда
				СтрокаТаблицаПеревода = ТаблицаПеревода.Найти(НРег(ПодТип),"ОригиналРусскийШагНРег");
				Если СтрокаТаблицаПеревода <> Неопределено Тогда
					Если ЗначениеЗаполнено(СтрокаТаблицаПеревода.ТекстПереводаШаг) Тогда
						ПодТип = СтрокаТаблицаПеревода.ТекстПереводаШаг;
					КонецЕсли;
					ЕстьПеревод = Истина;
				КонецЕсли;
			КонецЕсли;

			Если ПолныйТипШага = "" Тогда
				ПолныйТипШага = ПодТип;
			Иначе
				ПолныйТипШага = ПолныйТипШага + "." + ПодТип;
			КонецЕсли;

			НайденныеСтрокиДерева = ТекСтроки.НайтиСтроки(Новый Структура("ТипШага",ПодТип),Ложь);
			Если НайденныеСтрокиДерева.Количество() = 0 Тогда
				ТекСтрока               = ТекСтроки.Добавить();
				ТекСтрока.ТипШага       = ПодТип;
				ТекСтрока.ПолныйТипШага = ПолныйТипШага;
				ТекСтрока.Язык          = "ru";
				Если ТаблицаПеревода <> Неопределено и ЕстьПеревод Тогда
					ТекСтрока.Язык          = ЯзыкГенератораGherkin;
				КонецЕсли;

				ТекСтроки = ТекСтрока.Строки;
			Иначе
				ТекСтроки = НайденныеСтрокиДерева[0].Строки;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста

Функция ПреобразоватьТипПеревод(Тип,ТаблицаПеревода)
	МассивТип = РазложитьСтрокуВМассивПодстрок(Тип,".");
	ПолныйТипШага = "";
	Для Каждого ПодТип Из МассивТип Цикл
		СтрокаТаблицаПеревода = ТаблицаПеревода.Найти(НРег(ПодТип),"ОригиналРусскийШагНРег");
		Если СтрокаТаблицаПеревода <> Неопределено Тогда
			Если ЗначениеЗаполнено(СтрокаТаблицаПеревода.ТекстПереводаШаг) Тогда
				ПодТип = СтрокаТаблицаПеревода.ТекстПереводаШаг;
			КонецЕсли;
		КонецЕсли;

		Если ПолныйТипШага = "" Тогда
			ПолныйТипШага = ПодТип;
		Иначе
			ПолныйТипШага = ПолныйТипШага + "." + ПодТип;
		КонецЕсли;
	КонецЦикла;

	Возврат ПолныйТипШага;
КонецФункции

&НаСервере

Функция ДобавитьШаги(Дерево,Тип,Данные,ТаблицаПеревода,СтрТаблицаИзвестныхStepDefinition,ДопПараметры)

	Если ТаблицаПеревода <> Неопределено Тогда
		Тип = ПреобразоватьТипПеревод(Тип,ТаблицаПеревода);
	КонецЕсли;

	НайденныеСтрокиДерева = Дерево.Строки.НайтиСтроки(Новый Структура("ПолныйТипШага",Тип),Истина);
	Если НайденныеСтрокиДерева.Количество() = 0 Тогда
		ТекстСообщения = ПолучитьТекстСообщенияПользователюСервер("Не найден тип шага <%1>",ДопПараметры.ТекстСообщенийПользователю);
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",Тип);
		ВызватьИсключение(ТекстСообщения);
	КонецЕсли;

	СтрокаДерева = НайденныеСтрокиДерева[0];
	СтрокаШага   = СтрокаДерева.Строки.Добавить();
	СтрокаШага.ПредставлениеТеста = Данные.ПредставлениеТеста;
	СтрокаШага.ОписаниеШага       = ВставитьГиперссылкиВОписаниеШага(Данные.ОписаниеШага, ДопПараметры);
	СтрокаШага.ИмяПроцедуры       = Данные.СтрокаРеальнойПроцедуры;
	СтрокаШага.ТипШагаВДереве     = Данные.ТипШагаВДереве;
	Если СтрТаблицаИзвестныхStepDefinition <> Неопределено Тогда
		СтрокаШага.ОписаниеШагаОригинал = СтрТаблицаИзвестныхStepDefinition.ОписаниеШагаОригинал;
		СтрокаШага.ПредставлениеТестаОригинал = СтрТаблицаИзвестныхStepDefinition.ПредставлениеТестаОригинал;
	КонецЕсли;
	СтрокаШага.ИмяФайла = СтрЗаменить(Данные.ИмяФайла,"/","\");
	СтрокаШага.Язык = "ru";
	СтрокаШага.Снипет = Данные.ID;

	Если ТаблицаПеревода <> Неопределено Тогда
		СтрокаПоиска = СтрТаблицаИзвестныхStepDefinition.СтрокаДляПоиска;

		СтрокаТаблицаПеревода = ТаблицаПеревода.Найти(СтрокаПоиска,"СтрокаДляПоискаРусский");
		Если СтрокаТаблицаПеревода <> Неопределено Тогда
			СтрокаШага.Язык               = ЯзыкГенератораGherkin;
			Если ЗначениеЗаполнено(СтрокаТаблицаПеревода.ТекстПереводаШаг) Тогда
				СтрокаШага.ПредставлениеТеста = УбратьСлужебныеСимволыИзПредставления(СтрокаТаблицаПеревода.ТекстПереводаШаг);
			КонецЕсли;
			Если ЗначениеЗаполнено(СтрокаТаблицаПеревода.ТекстПереводаОписание) Тогда
				СтрокаШага.ОписаниеШага = СтрокаТаблицаПеревода.ТекстПереводаОписание;
			КонецЕсли;
		Иначе
			Если НЕ ДопПараметры.ЭтоРежимОбучения Тогда
				ТекстСообщения = ПолучитьТекстСообщенияПользователюСервер("Не найден перевод для шага <%1>",ДопПараметры.ТекстСообщенийПользователю);
				ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",Данные.ПредставлениеТеста);
				Сообщить(ТекстСообщения);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;

	Возврат СтрокаШага;

КонецФункции

&НаСервере

Процедура СортироватьДеревоШагов(Дерево)
	Дерево.Строки.Сортировать("ТипШага,ОписаниеШага",Истина);
КонецПроцедуры

&НаСервере


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало функция `УбратьСпецсимволыИспользованияПеременной`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Функция УбратьСпецсимволыИспользованияПеременной(Стр)
Если Лев(Стр, 2) = "$$" И Прав(Стр, 2) = "$$" Тогда
		Возврат Сред(Стр, 3, СтрДлина(Стр) - 4);
	КонецЕсли;

	Если Лев(Стр, 1) = "$" И Прав(Стр, 1) = "$" Тогда
    // TODO: допиши оставшуюся часть

[Assistant]
Функция УбратьСпецсимволыИспользованияПеременной(Стр)

	Если Лев(Стр, 2) = "$$" И Прав(Стр, 2) = "$$" Тогда
		Возврат Сред(Стр, 3, СтрДлина(Стр) - 4);
	КонецЕсли;

	Если Лев(Стр, 1) = "$" И Прав(Стр, 1) = "$" Тогда
		Возврат Сред(Стр, 2, СтрДлина(Стр) - 2);
	КонецЕсли;

	Возврат Стр;

КонецФункции

&НаКлиенте

Функция ВставитьГиперссылкиВОписаниеШага(Знач Стр, ДопПараметры)

	Для Каждого ДанныеЗамены Из ДопПараметры.ДанныеДляВставкиГиперссылокВОписаниеШагов Цикл
		Поз = Найти(НРег(Стр), ДанныеЗамены.НРегСтрокаПоиска);
		Если Поз > 0 Тогда

			ЛеваяЧасть = Лев(Стр, Поз - 1 + СтрДлина(ДанныеЗамены.НРегСтрокаПоиска));
			ПраваяЧасть = Сред(Стр, Поз + СтрДлина(ДанныеЗамены.НРегСтрокаПоиска));

			Стр = ЛеваяЧасть + " (" + ДанныеЗамены.Гиперссылка + ")" + ПраваяЧасть;

		КонецЕсли;
	КонецЦикла;

	Возврат Стр;

КонецФункции

&НаКлиентеНаСервереБезКонтекста

Функция ВерсияПриложенияБольшеИлиРавнаЧемЗаданная(Знач Версия1, Знач Версия2)

	Массив1 = РазложитьСтрокуВМассивПодстрок(Версия1, ".");
	Массив2 = РазложитьСтрокуВМассивПодстрок(Версия2, ".");

	Версия1БольшеИлиРавно = Истина;
	Для Ккк = 0 По Массив1.Количество() - 1 Цикл
		Элем1 = Массив1.Получить(Ккк);
		Элем2 = Массив2.Получить(Ккк);

		Если Число(Элем2) > Число(Элем1) Тогда
			Возврат Ложь;
		ИначеЕсли Число(Элем2) < Число(Элем1) Тогда
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Возврат Версия1БольшеИлиРавно;
КонецФункции

// Аналог СтрРазделить() для старых версий платформы
// Описание параметров аналогично описанию параметров для СтрРазделить()
&НаКлиентеНаСервереБезКонтекста

Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",", Знач ПропускатьПустыеСтроки = Неопределено,
		Знач ЕстьПоддержкаФункцияРазложитьСтрокуВМассивПодстрок = Ложь)

	Результат = Новый Массив;

	// для обеспечения обратной совместимости
	Если ПропускатьПустыеСтроки = Неопределено Тогда
		ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
		Если ПустаяСтрока(Строка) Тогда
			Если Разделитель = " " Тогда
				Результат.Добавить("");
			КонецЕсли;
			Возврат Результат;
		КонецЕсли;
	КонецЕсли;

	Если ЕстьПоддержкаФункцияРазложитьСтрокуВМассивПодстрок И СтрДлина(Разделитель) = 1 Тогда
		Если ПропускатьПустыеСтроки = Истина Тогда
			Возврат Вычислить("СтрРазделить(Строка,Разделитель,Ложь)");
		Иначе
			Возврат Вычислить("СтрРазделить(Строка,Разделитель,Истина)");
		КонецЕсли;
	КонецЕсли;

	Позиция = Найти(Строка, Разделитель);
	Пока Позиция > 0 Цикл
		Подстрока = Лев(Строка, Позиция - 1);
		Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
			Результат.Добавить(Подстрока);
		КонецЕсли;
		Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
		Позиция = Найти(Строка, Разделитель);
	КонецЦикла;

	Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
		Результат.Добавить(Строка);
	КонецЕсли;

	Возврат Результат;

КонецФункции

// Создаёт временный фича файл
&НаКлиенте
//Создаёт временный фича файл

Процедура VanessaEditorБыстроСоздатьВременныйФичаФайл() Экспорт
	Ванесса.ПодготовитьСценарийКВыполнению();
КонецПроцедуры

&НаКлиенте

Процедура ОбработчикНажатияГиперссылкиВФайлеMarkDown(Стр)

	Если НРег(Лев(СокрЛП(Стр), 4)) = "http" Тогда
		НачатьЗапускПриложения(Ванесса.ОписаниеПустогоОбработчика(2), Стр);
		Возврат;
	КонецЕсли;

	Ванесса.ЗапуститьУрокИнтерактивнойСправки(Стр);

КонецПроцедуры

&НаКлиенте

Процедура ОбновитьТекущуюСтрокуРедактораПоТекущейСтрокеДереваОбработчик()
	Если Ванесса.ДанныеДляОбновленияСтрокиРедактораПоТекущейСтрокеДерева = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если НЕ Ванесса.Объект.ИспользоватьРедакторVanessaEditor Тогда
		Возврат;
	КонецЕсли;

	Ванесса.АктивизироватьСтрокуРедактораПоИдСтрокиИНомеруСтрокиФичи(
		Ванесса.ДанныеДляОбновленияСтрокиРедактораПоТекущейСтрокеДерева.ИДСтроки,
		Ванесса.ДанныеДляОбновленияСтрокиРедактораПоТекущейСтрокеДерева.НомерСтрокиВФиче);
КонецПроцедуры

&НаКлиенте

Процедура ЗакрытьОсновнуюФормуТаймер()
	Ванесса.Закрыть();
КонецПроцедуры

&НаКлиенте

Процедура АктивизироватьСтрокуРедактораПоИдСтрокиИНомеруСтрокиФичиСлужебный(ИДСтроки, НомерСтрокиВФиче)

	ИдВиджета = Ванесса.ИдВиджетаПоИдСтроки(ИДСтроки);
	Если ИдВиджета <> Неопределено Тогда
		НомерСтроки = НомерСтрокиВнутриВиджета(ИдВиджета, ИДСтроки);
		Если НомерСтроки = Неопределено Тогда
			НомерСтроки = ПолучитьVanessaEditor().getWidgetLine(ИдВиджета);
		КонецЕсли;
		ПолучитьVanessaEditor().revealLineInCenter(НомерСтроки, ИдВиджета);
		ПолучитьVanessaEditor().setPosition(НомерСтроки, 1, ИдВиджета);
	Иначе
		ПолучитьVanessaEditor().revealLineInCenter(НомерСтрокиВФиче);
		ПолучитьVanessaEditor().setPosition(НомерСтрокиВФиче, 1, "");
	КонецЕсли;

КонецПроцедуры

&НаКлиенте

Функция НомерСтрокиВнутриВиджета(ИдВиджета, ИДСтроки)
	ДанныеВкладок = Ванесса.ДанныеВкладокРедактора[Ванесса.VanessaTabs.current.filename];

	Если ДанныеВкладок = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	Если ДанныеВкладок.ДанныеВиджетов[ИдВиджета] = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	Возврат ДанныеВкладок.ДанныеВиджетов[ИдВиджета][ИДСтроки];

КонецФункции

&НаКлиенте

Процедура ЗаменитьВТаблицаТекущееЗначение(ТаблицаТекущееЗначение, МассивСтрокТаблицыИзСценария, НомерПервойСтрокиТаблицы, ОставлятьСпецСимволы)

	Колонки = Ванесса.ЗначенияИзСтрокиТаблицыGherkin(МассивСтрокТаблицыИзСценария[0]);
	Для Сч = 0 По МассивСтрокТаблицыИзСценария.Количество() - 1 Цикл
		СтрокаТекущееЗначение = ТаблицаТекущееЗначение[Сч];
		СтрокаЭталонноеЗначение = МассивСтрокТаблицыИзСценария[Сч];

		ЭталонныеЗначения = Ванесса.ЗначенияИзСтрокиТаблицыGherkin(СтрокаЭталонноеЗначение);
		СчетчикКолонок = -1;
		Для СчетчикТекущихЗначений = 0 По ЭталонныеЗначения.Количество() - 1 Цикл
			СчетчикКолонок = СчетчикКолонок + 1;
			ТекЗначение = ЭталонныеЗначения[СчетчикТекущихЗначений];
			Если ОставлятьСпецСимволы И (Найти(ТекЗначение, "*") > 0 ИЛИ Найти(ТекЗначение, "$") > 0) Тогда
				Продолжить;
			КонецЕсли;

			ИмяКолонки = Ванесса.УбратьКавычкиАпострофы(Колонки[СчетчикКолонок].Значение);
			НовоеЗначение = СтрокаТекущееЗначение[СчетчикКолонок];
			Если НовоеЗначение = Неопределено Тогда
				ВызватьИсключение Ванесса.ПодставитьПараметрыВСтроку(Ванесса.Локализовать("В текущем значении таблицы не найдена колонка <%1>."), ИмяКолонки);
			КонецЕсли;

			НовоеЗначение = "'" + СтрЗаменить(НовоеЗначение, "'", "\'") + "'";
			НовоеЗначение = СтрЗаменить(НовоеЗначение, "|", "\|");
			ЭталонныеЗначения[СчетчикТекущихЗначений].Значение = НовоеЗначение;

		КонецЦикла;

		МассивСтрокТаблицыИзСценария[Сч] = "|" + Ванесса._СтрСоединить(ЭталонныеЗначения.ВыгрузитьЗначения(), "|") + "|";

	КонецЦикла;

	Ванесса.ФорматироватьМассивСтрокКакТаблицу(МассивСтрокТаблицыИзСценария);

	ЗаменитьТаблицуGherkinПослеРедактирования(МассивСтрокТаблицыИзСценария, НомерПервойСтрокиТаблицы);

КонецПроцедуры

&НаКлиенте

Процедура АктуализироватьТаблицуGherkinПриСравненииТабличногоДокументаПоДаннымОшибкиВРедактореПродолжение2(МассивСтрокТаблицыИзСценария, НомерПервойСтрокиТаблицы, ДанныеДляАктуализации)

	ТаблицаТекущееЗначение = ДанныеДляАктуализации.ТаблицаТекущееЗначение.Значение;

	ТаблицаРезультат = Новый Массив;
	Колонки = Ванесса.ЗначенияИзСтрокиТаблицыGherkin(МассивСтрокТаблицыИзСценария[0]);
	Для Сч = 0 По ТаблицаТекущееЗначение.Количество() - 1 Цикл
		ПромРезультат = Новый Массив;
		СтрокаТекущееЗначение = ТаблицаТекущееЗначение[Сч];
		Для СчетчикТекущихЗначений = 0 По СтрокаТекущееЗначение.Количество() - 1 Цикл
			ТекЗначение = СтрокаТекущееЗначение[СчетчикТекущихЗначений];

			НовоеЗначение = "'" + СтрЗаменить(ТекЗначение, "'", "\'") + "'";
			НовоеЗначение = СтрЗаменить(НовоеЗначение, "|", "\|");
			ПромРезультат.Добавить(НовоеЗначение);

		КонецЦикла;

		ТаблицаРезультат.Добавить("|" + Ванесса._СтрСоединить(ПромРезультат, "|") + "|");

	КонецЦикла;

	Ванесса.ФорматироватьМассивСтрокКакТаблицу(ТаблицаРезультат);

	ЗаменитьТаблицуGherkinПослеРедактирования(ТаблицаРезультат, НомерПервойСтрокиТаблицы);

КонецПроцедуры

&НаКлиенте


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(Версия1, Версия2)

    МассивВерсии1 = РазделитьСтроку(Версия1, ".");
    МассивВерсии2 = РазделитьСтроку(Версия2, ".");

    МаксДлина = Макс(МассивВерсии1.Количество(), МассивВерсии2.Количество());

    Для i = 0 По МаксДлина - 1 Цикл

        Число1 = 0;
        Если i < МассивВерсии1.Количество() Тогда
            Попытка
                Число1 = Число(МассивВерсии1[i]);
            Исключение
            КонецПопытки;
        КонецЕсли;

        Число2 = 0;
        Если i < МассивВерсии2.Количество() Тогда
            Попытка
                Число2 = Число(МассивВерсии2[i]);
            Исключение
            КонецПопытки;
        КонецЕсли;

        Если Число1 > Число2 Тогда
            Возврат 1; // Версия1 > Версия2
        ИначеЕсли Число1 < Число2 Тогда
            Возврат -1; // Версия1 < Версия2
        КонецЕсли;

    КонецЦикла;

    // Версии равны
    Возврат 0;

КонецФункции

&НаСервереБезКонтекста

Функция РазделитьСтроку(Строка, Разделитель)

    Результат = Новый Массив;

    Если Строка = "" Тогда
        Возврат Результат;
    КонецЕсли;

    Позиция = 1;
    ДлинаРазделителя = СтрДлина(Разделитель);

    Пока Позиция <= СтрДлина(Строка) Цикл
        СледующаяПозиция = НайтиВСтроке(Строка, Разделитель, Позиция);
        Если СледующаяПозиция > 0 Тогда
            Элемент = Сред(Строка, Позиция, СледующаяПозиция - Позиция);
            Результат.Добавить(Элемент);
            Позиция = СледующаяПозиция + ДлинаРазделителя;
        Иначе
            Элемент = Сред(Строка, Позиция);
            Результат.Добавить(Элемент);
            Позиция = СтрДлина(Строка) + 1;
        КонецЕсли;
    КонецЦикла;

    Возврат Результат;

КонецФункции

&НаСервереБезКонтекста

Функция НайтиВСтроке(Строка, Подстрока, НачальнаяПозиция)

    ДлинаСтроки = СтрДлина(Строка);
    ДлинаПодстроки = СтрДлина(Подстрока);

    Если ДлинаПодстроки = 0 Тогда
        Возврат НачальнаяПозиция;
    КонецЕсли;

    Для i = НачальнаяПозиция По ДлинаСтроки - ДлинаПодстроки + 1 Цикл
        Если Сред(Строка, i, ДлинаПодстроки) = Подстрока Тогда
            Возврат i;
        КонецЕсли;
    КонецЦикла;

    Возврат 0;

КонецФункции

&НаКлиенте

[Assistant] Функция СравнитьВерсии(Версия1, Версия2)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции() Экспорт
	Если Не ОбъектКонтекстСохраняемый.Свойство("ТестовоеПриложение") Тогда
		ВызватьИсключение Локализовать("Клиент тестирования не подключен.");
	КонецЕсли;

	Если ОбъектКонтекстСохраняемый.ТестовоеПриложение = Неопределено Тогда
		ВызватьИсключение Локализовать("Клиент тестирования не подключен.");
	КонецЕсли;

	Возврат ОбъектКонтекстСохраняемый.ТестовоеПриложение;
КонецФункции

// Фиксирует форму или группу элементов клиента тестирования, с которой будет происходить работа.
// В ней будет происходить поиск элементов формы.
&НаКлиенте

Процедура ЗафиксироватьФормуГруппуTestClient(ФормаПриложенияИлиГруппа) Экспорт
	ЗафиксированнаяФормаИлиГруппаTestClient = ФормаПриложенияИлиГруппа;
КонецПроцедуры

//Возвращает значение закфиксированной для поиска группы или формы.
&НаКлиенте

Функция ЗначениеЗафиксированногоКонтейнера() Экспорт
	Возврат ЗафиксированнаяФормаИлиГруппаTestClient;
КонецФункции

// Отменяет фиксирование группы элементов, в которой происходит поиск элементов
// В ней будет происходить поиск элементов формы.
&НаКлиенте

Процедура УбратьФиксированиеГруппыДляПоискаЭлементов() Экспорт
	Если ТипЗнч(ЗафиксированнаяФормаИлиГруппаTestClient) = Тип("ТестируемаяГруппаФормы") Тогда
		ЗафиксированнаяФормаИлиГруппаTestClient = Неопределено;
	КонецЕсли;
КонецПроцедуры

// проверяет видимость элмента формы с учетом родительских групп
&НаКлиенте

Функция ВидимостьЭлементаСУчетомРодителя(ТекущаяФормаЭлемента, ЭлементФормы, ТекущаяВидимость) Экспорт
	Если ТекущаяФормаЭлемента = Неопределено Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Для элемента с именем <%1> не найдена форма."),
			ЭлементФормы.Имя
		);
	КонецЕсли;

	Если НЕ ТекущаяВидимость Тогда
		// нет смысла проверять для невидимых элементов
		Возврат ТекущаяВидимость;
	КонецЕсли;

	Если Версия8325ИлиВыше И ПроверятьВидимостьЭлементаСУчетомРодителя = Истина Тогда
		Возврат ВидимостьЭлементаСУчетомРодителя8325(ТекущаяФормаЭлемента, ЭлементФормы, ТекущаяВидимость);
	КонецЕсли;

	Если ПроверятьВидимостьЭлементаСУчетомРодителя <> Истина Тогда
		Возврат ТекущаяВидимость;
	КонецЕсли;

	ГруппыФормы = ТекущаяФормаЭлемента.НайтиОбъекты(Тип("ТестируемаяГруппаФормы"));
	Для Каждого ТекГруппа Из ГруппыФормы Цикл
		ЭлементыГруппы = ТекГруппа.НайтиОбъекты();
		Если ЭлементыГруппы.Найти(ЭлементФормы) <> Неопределено Тогда
			Если НЕ ТекГруппа.ТекущаяВидимость() Тогда
				// значит элемент лежит в невидимой группе
				Возврат Ложь;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;

	Возврат ТекущаяВидимость;
КонецФункции

// Устанаваливает статус проверки видимости элемента с учетом видимости родительской группы
&НаКлиенте

Процедура УстановитьСтатусПроверятьВидимостьЭлементаСУчетомРодителя(Значение) Экспорт
	ПроверятьВидимостьЭлементаСУчетомРодителя = Значение;
КонецПроцедуры

&НаКлиенте

Процедура ОбработатьСменуАктивногоОкна(ДопПараметры = Неопределено) Экспорт
	ОчиститьКешАктивнойТаблицыTestClient();

	СбрасыватьЗафиксированнуюФорму = Истина;
	СбрасыватьЗафиксированнуюГруппу = Истина;
	Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
		Если ДопПараметры.Свойство("СбрасыватьЗафиксированнуюФорму") Тогда
			СбрасыватьЗафиксированнуюФорму = ДопПараметры.СбрасыватьЗафиксированнуюФорму;
		КонецЕсли;
		Если ДопПараметры.Свойство("СбрасыватьЗафиксированнуюГруппу") Тогда
			СбрасыватьЗафиксированнуюФорму = ДопПараметры.СбрасыватьЗафиксированнуюГруппу;
		КонецЕсли;
	КонецЕсли;

	Если СбрасыватьЗафиксированнуюФорму Тогда
		// убираем фиксацию формы, т.к. окно сменилось
		НадоСбросить = Истина;
		Если ТипЗнч(ЗафиксированнаяФормаИлиГруппаTestClient) = Тип("ТестируемаяГруппаФормы") И НЕ СбрасыватьЗафиксированнуюГруппу Тогда
			НадоСбросить = Ложь;
		КонецЕсли;

		Если НадоСбросить Тогда
			ЗафиксироватьФормуГруппуTestClient(Неопределено);
		КонецЕсли;
	КонецЕсли;

	ЗапомнитьАктивноеОкно(Неопределено);
КонецПроцедуры

// Закрывает все окна клиентсткого приложения
&НаКлиенте

[Assistant] Функция ПолучитьТестовоеПриложение()


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ДопПараметры = Неопределено) Экспорт
	Если ЗафиксированнаяФормаИлиГруппаTestClient <> Неопределено Тогда
		Массив = Новый Массив;
		Массив.Добавить(ЗафиксированнаяФормаИлиГруппаTestClient);
		Возврат Массив;
	КонецЕсли;

	ОкноПриложения = ПолучитьАктивноеОкноИзТестовоеПриложение(ДопПараметры);
	Если ОкноПриложения = Неопределено Тогда
		ВызватьИсключение Локализовать("Не получилось определить активное окно Клиента тестирования.");
	КонецЕсли;

	Если ОкноПриложения.НачальнаяСтраница Тогда
		МассивФорм = ОкноПриложения.НайтиОбъекты(Тип("ТестируемаяФорма"));
	Иначе
		ТекФорма = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"));
		МассивФорм = Новый Массив;
		МассивФорм.Добавить(ТекФорма);
	КонецЕсли;

	Если ДопПараметры <> Неопределено Тогда
		ДопПараметры.Вставить("АктивноеОкно", ОкноПриложения);
	КонецЕсли;
	Возврат МассивФорм;
КонецФункции

&НаКлиенте

Функция НайтиФормыОкнаИзКонтекста(ДопПараметры = Неопределено) Экспорт
	ОкноПриложения         = ПолучитьАктивноеОкноИзКонтекста();
	Если ОкноПриложения = Неопределено Тогда
		ВызватьИсключение Локализовать("Не получилось определить активное окно Клиента тестирования из Контекста.");
	КонецЕсли;

	Попытка
		МассивФорм = ОкноПриложения.НайтиОбъекты(Тип("ТестируемаяФорма"));
	Исключение
		// Скорее всего окно уже закрылось, но пока ещё есть в контексте.
		Возврат Неопределено;
	КонецПопытки;

	Возврат МассивФорм;
КонецФункции

&НаКлиенте

Функция НайтиОкноМодальногоДиалога(ТолькоПредупреждение = Ложь) Экспорт
	НужноеОкно = Неопределено;

	ОкнаПриложения = ОбъектКонтекстСохраняемый.ТестовоеПриложение.НайтиОбъекты(Тип("ТестируемоеОкноКлиентскогоПриложения"));
	Для Каждого ОкноПриложения Из ОкнаПриложения Цикл
		Если ЭтоЗаголовокОкнаМодальногоДиалога(ОкноПриложения.Заголовок)
			ИЛИ ((ОкноПриложения.Заголовок = "Выбор типа данных") И НЕ ТолькоПредупреждение)
			ИЛИ ((ОкноПриложения.Заголовок = "Список значений") И НЕ ТолькоПредупреждение)
			ИЛИ ((ОкноПриложения.Заголовок = "Данные были изменены") И НЕ ТолькоПредупреждение)
			ИЛИ ((ОкноПриложения.Заголовок = "Предупреждение безопасности") И НЕ ТолькоПредупреждение)
			Тогда
			НужноеОкно = ОкноПриложения;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Если НужноеОкно <> Неопределено Тогда
		ЗапомнитьАктивноеОкно(НужноеОкно);
	КонецЕсли;

	Возврат НужноеОкно;
КонецФункции

// Проверяет, что переданное окно является модальным диалогом
&НаКлиенте

Функция ЭтоМодальныйДиалог(ОкноПриложения) Экспорт
	Если ЭтоЗаголовокОкнаМодальногоДиалога(ОкноПриложения.Заголовок) Тогда
		Возврат Истина;
	КонецЕсли;

	Если ОкноПриложения.Основное Тогда
		Возврат Ложь;
	КонецЕсли;

	Попытка
		ФормаОкна = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"));
	Исключение
		Возврат Ложь;
	КонецПопытки;

	Если ФормаОкна = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Если ФормаОкна.ИмяФормы = "" Тогда
		Возврат Истина;
	КонецЕсли;
	Если ФормаОкна.ИмяФормы = "MessageBox" Тогда
		Возврат Истина;
	ИначеЕсли ФормаОкна.ИмяФормы = "ErrorWindow" Тогда
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;
КонецФункции

&НаКлиенте

Функция ЭтоЗаголовокОкнаМодальногоДиалога(Заголовок) Экспорт
	Если Заголовок = "1С:Предприятие" Тогда
		Возврат Истина;
	ИначеЕсли Заголовок = "1C:Enterprise" Тогда
		Возврат Истина;
	ИначеЕсли Заголовок = "Отчет об ошибке" Тогда
		Возврат Истина;
	ИначеЕсли Заголовок = "Report about error" Тогда
		Возврат Истина;
	ИначеЕсли Заголовок = "Подробный текст ошибки" Тогда
		Возврат Истина;
	ИначеЕсли Заголовок = "Error info" Тогда
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;
КонецФункции

&НаКлиенте

Функция НайтиФормуПоЗаголовку(ИмяФормы) Экспорт
	ОкноПриложения = ПолучитьАктивноеОкноИзТестовоеПриложение();
	НужнаяФорма = Неопределено;
	Если ОкноПриложения <> Неопределено Тогда
		НужнаяФорма = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"), ИмяФормы);
	КонецЕсли;
	Если НужнаяФорма = Неопределено Тогда
		// Иногда 1С некорректно отдаёт текущее окно, тогда будем искать во всех окнах
		// сначала поищем в недавно открытом окне

		Попытка
			ОкноПриложения = ПолучитьАктивноеОкноИзКонтекста();
			НужнаяФорма    = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"), ИмяФормы);
			Если НужнаяФорма <> Неопределено Тогда
				ЗапомнитьАктивноеОкно(ОкноПриложения); // произошла неявная смена активного окна
				Возврат НужнаяФорма;
			КонецЕсли;
		Исключение

		КонецПопытки;

		// затем будем искать во всех окнах
		МассивОкон = ОбъектКонтекстСохраняемый.ТестовоеПриложение.НайтиОбъекты(Тип("ТестируемоеОкноКлиентскогоПриложения"));
		Для каждого ТекОкно Из МассивОкон Цикл

			НужнаяФорма    = ТекОкно.НайтиОбъект(Тип("ТестируемаяФорма"), ИмяФормы);
			Если НужнаяФорма <> Неопределено Тогда
				ЗапомнитьАктивноеОкно(ТекОкно); // произошла неявная смена активного окна
				Возврат НужнаяФорма;
			КонецЕсли;

		КонецЦикла;
	КонецЕсли;

	Если НужнаяФорма = Неопределено Тогда
		СообщитьПользователюИВызватьИсключение(ПодставитьПараметрыВСтроку(
			Локализовать("Форма с заголовком <%1> не найдена."),
			ИмяФормы
		));
	КонецЕсли;

	ЗапомнитьАктивноеОкно(ОкноПриложения); // произошла неявная смена активного окна
	Возврат НужнаяФорма;
КонецФункции

// Использовать, когда известно, что у текущего окна только одна форма, иначе надо использовать НайтиФормыТекущегоОкна()
&НаКлиенте

Функция НайтиТекущуюФормуTestClient() Экспорт
    Получилось = Истина;
    Попытка
        ОкноПриложения         = ПолучитьАктивноеОкноИзКонтекста();
        ТекущаяФорма           = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"));
    Исключение
        Получилось = Ложь;
    КонецПопытки;

    Если Не Получилось Тогда
        ОкноПриложения = ПолучитьАктивноеОкноИзТестовоеПриложение();

		Попытка
	        ТекущаяФорма = ОкноПриложения.НайтиОбъект(Тип("ТестируемаяФорма"));
		Исключение
			Возврат Неопределено;
		КонецПопытки;

		ЗапомнитьАктивноеОкно(ОкноПриложения); // произошла неявная смена активного окна
    КонецЕсли;

    Возврат ТекущаяФорма;
КонецФункции

&НаКлиенте

Процедура ПолучитьПараметрыОбластиМакета(Знач ИмяОбласти, НачСтр, НачКол, КолСтр, КолКол) Экспорт
	ИмяОбластиОригинал = ИмяОбласти;

	ИмяОбласти = СокрЛП(ВРег(ИмяОбласти));
	Поз = Найти(ИмяОбласти, "R");
	Если Поз = 0 Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Неверный формат области <%1>"),
			ИмяОбластиОригинал
		);
	КонецЕсли;

	ИмяОбласти = Сред(ИмяОбласти, Поз + 1);
	Поз = Найти(ИмяОбласти, "C");
	Если Поз = 0 Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Неверный формат области <%1>"),
			ИмяОбластиОригинал
		);
	КонецЕсли;
	НачСтр = Число(Лев(ИмяОбласти, Поз - 1));

	ИмяОбласти = Сред(ИмяОбласти, Поз + 1);
	Поз = Найти(ИмяОбласти, ":");
	Если Поз = 0 Тогда
		КолСтр = НачСтр;
		Поз = Найти(ИмяОбластиОригинал, "C");
		НачКол = Число(Сред(ИмяОбластиОригинал, Поз + 1));
		КолКол = НачКол;
		Возврат;
	КонецЕсли;
	НачКол = Число(Лев(ИмяОбласти, Поз - 1));

	ИмяОбласти = Сред(ИмяОбласти, Поз + 1);

	ИмяОбласти = СокрЛП(ВРег(ИмяОбласти));
	Поз = Найти(ИмяОбласти, "R");
	Если Поз = 0 Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Неверный формат области <%1>"),
			ИмяОбластиОригинал
		);
	КонецЕсли;

	// вторая часть, после символа :

	ИмяОбласти = Сред(ИмяОбласти, Поз + 1);
	Поз = Найти(ИмяОбласти, "C");
	Если Поз = 0 Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Неверный формат области <%1>"),
			ИмяОбластиОригинал
		);
	КонецЕсли;
	КолСтр = Число(Лев(ИмяОбласти, Поз - 1)) - НачСтр + 1;

	ИмяОбласти = Сред(ИмяОбласти, Поз + 1);
	КолКол = Число(ИмяОбласти) - НачКол + 1;
КонецПроцедуры

&НаКлиенте

[Assistant] Функция НайтиКонтейнерыТекущегоОкнаTestClient(ДопПараметры = Неопределено)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции() Экспорт
	Если Версия8316ИлиВыше Тогда
		Возврат Ложь;
	КонецЕсли;

	Если Не ОбъектКонтекстСохраняемый.Свойство("ТестовоеПриложение") Тогда
		Возврат Ложь;
	КонецЕсли;

	Попытка
		НужноеОкно = ОбъектКонтекстСохраняемый.ТестовоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения")
		, "1С:Предприятие. Доступ к информационной базе");
	Исключение
		Возврат Ложь;
	КонецПопытки;

	Если НужноеОкно = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Возврат Истина;
КонецФункции

&НаКлиенте

Функция ПроверитьПортНаЗанятость(Знач Порт = 48000) Экспорт

	Если Порт <= 0 Или Порт > 65536 Тогда
		Порт = 48000;
	КонецЕсли;

	НачалоДиапазонаПортов    = 48000;
	ОкончаниеДиапазонаПортов = 50000;

	Если ЗначениеЗаполнено(Объект.ДиапазонПортовTestclient) Тогда
		// там должна быть строка вида 48000-48020
		МассивЗначений = РазложитьСтрокуВМассивПодстрокКлиент(Объект.ДиапазонПортовTestclient, "-");
		Если МассивЗначений.Количество() <> 2 Тогда
			ВызватьИсключение ПодставитьПараметрыВСтроку(
				Локализовать("Указан неверный диапазон портов: <%1>"),
				Объект.ДиапазонПортовTestclient
			);
		КонецЕсли;
		НачалоДиапазонаПортов = Число(МассивЗначений[0]);
		ОкончаниеДиапазонаПортов = Число(МассивЗначений[1]);
		Порт = НачалоДиапазонаПортов;
	КонецЕсли;

	МассивЗанятыхПортов = ПолучитьМассивЗанятыхПортов();
	Для Каждого ТекПорт Из МассивЗанятыхПортов Цикл
		ПортыКоторыеСчитаютсяЗанятыми.Вставить(ТекПорт, Истина);
	КонецЦикла;

	//Первый проход. Проверяем, что порт свободен сейчас и никогда не был занят.
	Если МассивЗанятыхПортов.Найти(Порт) <> Неопределено Тогда
		СвободныйПорт = НачалоДиапазонаПортов;
		// найти свободный порт в диапазоне
		Для Счетчик = НачалоДиапазонаПортов По ОкончаниеДиапазонаПортов Цикл
			Если МассивЗанятыхПортов.Найти(Счетчик) = Неопределено И ПортыКоторыеСчитаютсяЗанятыми[Счетчик] = Неопределено Тогда
				Возврат Счетчик;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	//Второй проход. Проверяем, что порт свободен сейчас.
	Если МассивЗанятыхПортов.Найти(Порт) <> Неопределено Тогда
		СвободныйПорт = НачалоДиапазонаПортов;
		// найти свободный порт в диапазоне
		Для Счетчик = НачалоДиапазонаПортов По ОкончаниеДиапазонаПортов Цикл
			Если МассивЗанятыхПортов.Найти(Счетчик) = Неопределено Тогда
				Возврат Счетчик;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	Возврат Порт;

КонецФункции // ПолучитьСвободныйПорт()

&НаКлиенте

Функция ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующий(ДопПараметр = "", СтрокаОшибки = Неопределено) Экспорт

	ТекущиеДанные = Элементы.ДанныеКлиентовТестирования.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		ПараметрыОтбора = Новый Структура;
		ПараметрыОтбора.Вставить("ЭтотКлиент", Истина);
	Иначе
		ПараметрыОтбора = Новый Структура;
		ПараметрыОтбора.Вставить("Имя", ТекущиеДанные.Имя);
	КонецЕсли;

	НайденныеСтроки = ДанныеКлиентовТестирования.НайтиСтроки(ПараметрыОтбора);
	Если НайденныеСтроки.Количество() > 0 Тогда
		ДанныеЗапускаКлиентаТестирования = НайденныеСтроки[0];
	КонецЕсли;

	Если ЗначениеЗаполнено(ДопПараметр) Тогда
		ДанныеЗапускаКлиентаТестирования.ДопПараметры = ДопПараметр;
	КонецЕсли;

	РезультатПодключения = ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующийДляНесколькихКлиентов(ДанныеЗапускаКлиентаТестирования, СтрокаОшибки);

	Возврат РезультатПодключения;

КонецФункции

// Возвращает массив
// каждая строка массива - массив значений исходного табличного документа
// если возможно используется ЗаписатьСодержимоеВФайл
// для web клиента и для платформы меньше 8.3.8 - считывает макет по ячейкам, согласно указанных параметров
// если использовался метод ЗаписатьСодержимоеВФайл - будет взята только часть макета, согласно указанных параметров
// чтения макета параметры чтения макета задаются через шаг: Тогда Я задаю системные параметры считывания макета НачСтр
// 1 НачКол 1 КолСтр 5 КолКол 3
&НаКлиенте

[Assistant] Функция НаЭкранеДиалогАвторизации()


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ЭлементФормы, ДопПараметры = Неопределено) Экспорт
	#Если НЕ ВебКлиент Тогда

	Если Объект.ПолучатьМакетыСПомощьюРасширенияVAExtension Тогда
		Возврат ТабличныйДокументИзКлиентаТестированияЧерезРасширение(ЭлементФормы, ДопПараметры);
	КонецЕсли;

	СистемнаяИнформация = Новый СистемнаяИнформация;
	ОжиданиеЗаполненияТабличногоДокумента(ЭлементФормы);
	Если НЕ ТекущийTestclientЭтоWebКлиент И Версия838ИлиВыше И СохранениеМакетовВФайлПриЧтенииДанных Тогда

		// значит можно сохранить макет в файл и пробросить в TestManager
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла("mxl");

		ТекущаяДоступность = Истина;
		Попытка
			ТекущаяДоступность = ЭлементФормы.ТекущаяДоступность();
		Исключение
		КонецПопытки;

		Если ТекущаяДоступность Тогда
			УстановитьРезультатДиалогаВыбораФайла(Истина, ИмяВременногоФайла, Неопределено);
			Если Версия8325ИлиВыше Тогда
				ЭлементФормы.ЗаписатьСодержимоеВФайл(Истина);
			Иначе
				ЭлементФормы.ЗаписатьСодержимоеВФайл();
			КонецЕсли;

			КоличествоПопытокПроверкиСуществованияФайла     = 0;
			МаксКоличествоПопытокПроверкиСуществованияФайла = ЗначениеКоличествоПопытокВыполненияДействия();
			МаксКоличествоПопытокПроверкиСуществованияФайла = Макс(МаксКоличествоПопытокПроверкиСуществованияФайла, 5);
			Пока Истина Цикл
				КоличествоПопытокПроверкиСуществованияФайла = КоличествоПопытокПроверкиСуществованияФайла + 1;
				Если КоличествоПопытокПроверкиСуществованияФайла > МаксКоличествоПопытокПроверкиСуществованияФайла Тогда
					Прервать;
				КонецЕсли;

				Если ФайлСуществуетКомандаСистемы(ИмяВременногоФайла) Тогда
					ТекстСообщения = ПодставитьПараметрыВСтроку(Локализовать("Табличный документ сохранен во временный файл <%1>"), ИмяВременногоФайла);
					ЗаписатьЛогВЖРИнформация("ПолучитьТабличныйДокументTestClient", ТекстСообщения);
					Прервать;
				КонецЕсли;

				Если НЕ Версия8325ИлиВыше Тогда
					// Если используется 8.3.25 и выше, то эмулируется вызов "Сохранить как", а не "Сохранить" и там нет проблемы, что происходит повторное сохранение в файл с тем же именем
					Если КоличествоПопытокПроверкиСуществованияФайла = 1 Тогда
						ПромФайл = ФайлМакетаВФайлахКоторыеИспользовалисьРанееВЭтомЖеСценарии();
						Если ПромФайл <> Неопределено Тогда
							ИмяВременногоФайла = ПромФайл;
							Прервать;
						КонецЕсли;
					КонецЕсли;
				КонецЕсли;

				Sleep(1);
			КонецЦикла;
		Иначе
			Возврат ТабличныйДокументTestClientПоЯчейкам(ЭлементФормы, ДопПараметры);
		КонецЕсли;

		Если Не ФайлСуществуетКомандаСистемы(ИмяВременногоФайла) Тогда
			ИмяВременногоФайла = ФайлМакетаВФайлахКоторыеИспользовалисьРанееВЭтомЖеСценарии();
			// Значит либо файл не успел сохраниться, либо ТабличныйДокумент не доступен для редактирования, и просто не может
			// сохранить файл значит надо считать ТабличныйДокумент по ячейкам
			Если ИмяВременногоФайла = Неопределено Тогда
				Возврат ТабличныйДокументTestClientПоЯчейкам(ЭлементФормы, ДопПараметры);
			КонецЕсли;
		КонецЕсли;

		КоличествоПопытокПолученияДвоичныхДанных     = 0;
		МаксКоличествоПопытокПолученияДвоичныхДанных = ЗначениеКоличествоПопытокВыполненияДействия();
		МаксКоличествоПопытокПолученияДвоичныхДанных = Макс(МаксКоличествоПопытокПолученияДвоичныхДанных, 15);
		Пока Истина Цикл
			КоличествоПопытокПолученияДвоичныхДанных = КоличествоПопытокПолученияДвоичныхДанных + 1;

			Попытка
				ФайлМакета = Новый ДвоичныеДанные(ИмяВременногоФайла);
				ТекстСообщения = ПодставитьПараметрыВСтроку(Локализовать("Получены двоичные данные макета из файла <%1>"), ИмяВременногоФайла);
				ЗаписатьЛогВЖРИнформация("ПолучитьТабличныйДокументTestClient", ТекстСообщения);
				Прервать;
			Исключение

			КонецПопытки;

			Если КоличествоПопытокПолученияДвоичныхДанных > МаксКоличествоПопытокПолученияДвоичныхДанных Тогда
				ВызватьИсключение ПодставитьПараметрыВСтроку(
					Локализовать("Не вышло получить данные файла <%1>"),
					ИмяВременногоФайла
				);
			КонецЕсли;

			Sleep(1);
		КонецЦикла;

		ЗапомнитьДанныеФайлаПриСохраненииМакета(ИмяВременногоФайла);

		НадоСчитатьОбласть = Ложь;
		Если ДопПараметры <> Неопределено Тогда
			Если ДопПараметры.Свойство("НадоСчитатьОбласть") Тогда
				НадоСчитатьОбласть = ДопПараметры.НадоСчитатьОбласть;
			КонецЕсли;
		КонецЕсли;

		Если НадоСчитатьОбласть Тогда
			ТабДок = ОставитьЧастьМакетаСогласноПараметровЧтенияМакета(ФайлМакета, ДопПараметры.НачСтр,
				ДопПараметры.НачКол, ДопПараметры.КолСтр, ДопПараметры.КолКол);
		Иначе
			ТабДок = ТабличныйДокументИзДвоичныхДанных(ФайлМакета);
			ФайлМакета = Новый ДвоичныеДанные(ИмяВременногоФайла);
			ТекстСообщения = ПодставитьПараметрыВСтроку(Локализовать("Получен табличный документ из двоичных данных <%1>"), ИмяВременногоФайла);
			ЗаписатьЛогВЖРИнформация("ПолучитьТабличныйДокументTestClient", ТекстСообщения);
		КонецЕсли;

		УдалитьФайлыКомандаСистемы(ИмяВременногоФайла);

		Возврат ТабДок;
	Иначе
		// значит надо считывать макет по ячейке
		Возврат ТабличныйДокументTestClientПоЯчейкам(ЭлементФормы, ДопПараметры);
	КонецЕсли;
	#КонецЕсли
КонецФункции

&НаКлиенте

[Assistant] Функция ПолучитьТабличныйДокументTestClient(ЭлементФормы, ДопПараметры = Неопределено)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ЭлементФормы, ДопПараметры = Неопределено) Экспорт
	ВыделятьВсеСтроки = Истина;
	ПроверкаКоличестваСтрок = Ложь;
	ВидСравненияТаблицы = Неопределено;
	ЗначениеСравнения = 0;
	НадоПолучитьТолькоНесколькоСтрок = Ложь;
	ВыполнятьОбновлениеТаблицы = Ложь;
	ВыполнятьУпорядочиваниеПоКолонкам = Ложь;
	Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
		Если ДопПараметры.Свойство("ВыделятьВсеСтроки") Тогда
			ВыделятьВсеСтроки = ДопПараметры.ВыделятьВсеСтроки;
		КонецЕсли;
		Если ДопПараметры.Свойство("ПроверкаКоличестваСтрок") Тогда
			ПроверкаКоличестваСтрок = ДопПараметры.ПроверкаКоличестваСтрок;
		КонецЕсли;
		Если ДопПараметры.Свойство("ВидСравненияТаблицы") Тогда
			ВидСравненияТаблицы = ДопПараметры.ВидСравненияТаблицы;
		КонецЕсли;
		Если ДопПараметры.Свойство("ЗначениеСравнения") Тогда
			ЗначениеСравнения = ДопПараметры.ЗначениеСравнения;
		КонецЕсли;
		Если НРег(ВидСравненияТаблицы) = "больше" ИЛИ ВидСравненияТаблицы = ">" Тогда
			НадоПолучитьТолькоНесколькоСтрок = Истина;
		КонецЕсли;
		Если ДопПараметры.Свойство("ВыполнятьОбновлениеТаблицы") Тогда
			ВыполнятьОбновлениеТаблицы = ДопПараметры.ВыполнятьОбновлениеТаблицы;
		КонецЕсли;
		Если ДопПараметры.Свойство("ВыполнятьУпорядочиваниеПоКолонкам") Тогда
			ВыполнятьУпорядочиваниеПоКолонкам = ДопПараметры.ВыполнятьУпорядочиваниеПоКолонкам;
		КонецЕсли;
	КонецЕсли;

	КоличествоПопыток = ЗначениеКоличествоПопытокВыполненияДействия();
	Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
		Если ДопПараметры.Свойство("КоличествоПопыток") Тогда
			КоличествоПопыток = ДопПараметры.КоличествоПопыток;
		КонецЕсли;
	КонецЕсли;

	Для СчетчикПопыток = 1 По КоличествоПопыток Цикл
		ТекущийРежимРедактирование = Ложь;
		Попытка
			ТекущийРежимРедактирование = ЭлементФормы.ТекущийРежимРедактирование();
		Исключение
		КонецПопытки;

		Если ТекущийРежимРедактирование Тогда
			Попытка
				ЭлементФормы.ЗакончитьРедактированиеСтроки();
			Исключение
			КонецПопытки;
		КонецЕсли;

		НадоПолучатьСтроки = Истина;
		ЗначениеТЧ         = Новый Массив;

		Попытка
			Если СчетчикПопыток > 1 Или ВыполнятьОбновлениеТаблицы Тогда
				ОбновитьСодержимоеТестируемойТаблицыФормы(ЭлементФормы, ДопПараметры);
			КонецЕсли;
		Исключение
		КонецПопытки;

		Попытка
			Если ВыделятьВсеСтроки Тогда
				ЭлементФормы.ПерейтиКПервойСтроке();
			КонецЕсли;
		Исключение
			// значит это не таблица
			НадоПолучатьСтроки = Ложь;
			ЗначениеТЧ         = Неопределено;
		КонецПопытки;

		Если НадоПолучатьСтроки  Тогда
			Попытка
				ТекЭлемент = ЭлементФормы.ПолучитьТекстЯчейки();

				Если ВыделятьВсеСтроки Тогда
					ЭлементФормы.ВыделитьВсеСтроки();
					// чтобы дать web клиенту успеть выделить строки
					Если ТекущийTestclientЭтоWebКлиент И БезопасноеВыполнениеШагов() Тогда
						sleep(1);
					КонецЕсли;
				КонецЕсли;

				ЗначениеТЧ = ЭлементФормы.ПолучитьВыделенныеСтроки();

				Если ЗначениеТЧ <> Неопределено И ЗначениеТЧ.Количество() = 0 И НЕ ВыделятьВсеСтроки Тогда
					//Возможно это интерфейс 8.5 и нет выделенных строк
					ПоляТаблицы = ЭлементФормы.НайтиОбъекты(Тип("ТестируемоеПолеФормы"));
					СтрокаТаблицы = Новый Соответствие;
					Для Каждого ТекПоле Из ПоляТаблицы Цикл
						Попытка
							Значение = ЭлементФормы.ПолучитьТекстЯчейки(ТекПоле.Имя);
							СтрокаТаблицы.Вставить(ТекПоле.ТекстЗаголовка, Значение);
						Исключение

						КонецПопытки;
					КонецЦикла;

					Если СтрокаТаблицы.Количество() > 0 Тогда
						ЗначениеТЧ = Новый Массив;
						ЗначениеТЧ.Добавить(СтрокаТаблицы);
						ЗначениеТЧ = Новый ФиксированныйМассив(ЗначениеТЧ);
					КонецЕсли;

				КонецЕсли;

				НадоПолучатьСтроки = Ложь;
			Исключение
			КонецПопытки;
		КонецЕсли;

		Если НадоПолучатьСтроки Тогда
			// для случая когда в таблице нет строк
			Попытка
				ЗначениеТЧ = ЭлементФормы.ПолучитьВыделенныеСтроки();
			Исключение
				СообщитьПользователю(ОписаниеОшибки());
			КонецПопытки;
		КонецЕсли;

		Если ВыделятьВсеСтроки И (ЗначениеТЧ <> Неопределено) И (ЗначениеТЧ.Количество() = 1) Тогда
			// значит возможна ситуация, когда в таблице запрещено получение всех строк

			ЗначениеТЧ = Новый Массив;

			// будем получать значение таблицы через переход к каждой строке
			ЭлементФормы.ПерейтиКПервойСтроке();

			КоличествоПолученныхСтрок = 0;
			Пока Истина Цикл
				СтрокаТаблицы = ЭлементФормы.ПолучитьВыделенныеСтроки();
				Если СтрокаТаблицы.Количество() <> 1 Тогда
					//Такое возможно, если это форма списка в режиме "Иерархический список" и открыта группа и в этой группе нет строк
					Прервать;
				КонецЕсли;

				ЗначениеТЧ.Добавить(СтрокаТаблицы[0]);
				КоличествоПолученныхСтрок = КоличествоПолученныхСтрок + 1;

				Если ПроверкаКоличестваСтрок
						И НадоПолучитьТолькоНесколькоСтрок
						И КоличествоПолученныхСтрок > ЗначениеСравнения Тогда
					Прервать;
				КонецЕсли;

				Попытка
					ЭлементФормы.ПерейтиКСледующейСтроке();
				Исключение
					Прервать;
				КонецПопытки;
			КонецЦикла;
		КонецЕсли;

		Если ЗначениеТЧ <> Неопределено Тогда
			Если ВыполнятьУпорядочиваниеПоКолонкам Тогда
				УпорядочитьЗначениеТаблицыФормыПоПорядкуКолонокЕслиЭтоВозможно(ЭлементФормы, ЗначениеТЧ);
			КонецЕсли;
			Прервать;
		КонецЕсли;

		Если СчетчикПопыток < КоличествоПопыток Тогда
			sleep(1);
		КонецЕсли;

	КонецЦикла;

	Возврат ЗначениеТЧ;
КонецФункции

&НаКлиенте

Процедура ОбновитьСодержимоеТестируемойТаблицыФормы(ЭлементФормы, ДопПараметры = Неопределено) Экспорт

	Если НЕ Объект.ОбновлятьТаблицыФормыПриПолученииЗначения Тогда
		Возврат;
	КонецЕсли;

	Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда

		Если НЕ ДопПараметры.Свойство("ВыполнятьОбновлениеТаблицы") Тогда
			Возврат;
		КонецЕсли;

		Если НЕ ДопПараметры.ВыполнятьОбновлениеТаблицы Тогда
			Возврат;
		КонецЕсли;

	КонецЕсли;

	Если ТипЗнч(ДопПараметры) <> Тип("Структура")
		И ДопПараметры <> Неопределено Тогда
		Возврат;
	КонецЕсли;

	Попытка
		ОбновитьСодержимоеТестируемойТаблицыФормыВПопытке(ЭлементФормы, ДопПараметры);
	Исключение
		// По каким то причинам обновить таблицу формы не получилось
	КонецПопытки;

КонецПроцедуры

&НаКлиенте

Процедура ЗапомнитьСостояниеФормыTestClient() Экспорт
	ДопПараметры = Новый Структура;
	СохраненноеСостояниеФормыTestClient = ПолучитьСостояниеФормыTestClient(ДопПараметры);
	Элементы.ПолучитьИзмененияФормыGherkin.Заголовок = Локализовать("Получить изменения формы в виде шагов");
	Элементы.VanessaEditorПолучитьИзмененияФормыGherkin.Заголовок = Элементы.ПолучитьИзмененияФормыGherkin.Заголовок;
	Элементы.VanessaEditorКонтекстноеМенюПолучитьИзмененияФормыGherkin.Заголовок = Элементы.ПолучитьИзмененияФормыGherkin.Заголовок;
КонецПроцедуры

&НаКлиенте

Процедура ЗабытьСостояниеФормыTestClient() Экспорт
	СохраненноеСостояниеФормыTestClient = Неопределено;
	Элементы.ПолучитьИзмененияФормыGherkin.Заголовок = Локализовать("Получить состояние всей формы в виде шагов");
	Элементы.VanessaEditorПолучитьИзмененияФормыGherkin.Заголовок = Элементы.ПолучитьИзмененияФормыGherkin.Заголовок;
	Элементы.VanessaEditorКонтекстноеМенюПолучитьИзмененияФормыGherkin.Заголовок = Элементы.ПолучитьИзмененияФормыGherkin.Заголовок;
КонецПроцедуры

&НаКлиенте

Процедура ПолучитьСостояниеТекущегоЭлементаФормы() Экспорт
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("ТолькоАктивныйЭлемент", Истина);
	ДопПараметры.Вставить("ВыполнятьУпорядочиваниеПоКолонкам", Истина);
	ПолучитьИзмененияФормы("Gherkin", ДопПараметры);
	СделатьПереводСгенерированногоТекстаGherkin();

	Если Объект.ИспользоватьРедакторVanessaEditor И Элементы.ФункциональностьЗакладки.ТекущаяСтраница = Элементы.ГруппаЗапускТестов Тогда
		Если НЕ ВозможенЗапускСценариевИзТекущейВкладки() Тогда
			Возврат;
		КонецЕсли;
		МодульРедакторТекста().ВставитьТекстСУчетомФорматирования(Объект.СгенерированныйСценарий);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ПолучитьИзмененияФормыGherkin() Экспорт
	ДопПараметры = Новый Структура;
	ПолучитьИзмененияФормы("Gherkin", ДопПараметры);
КонецПроцедуры

&НаКлиенте

[Assistant] Функция ПолучитьЗначениеТестируемаяТаблицаФормы(ЭлементФормы, ДопПараметры = Неопределено)


[System] Ты анализируешь код 1С и подбираешь точные имена для процедур и функций.

[User]
Восстанови осмысленное имя процедуры или функции на 1С по её телу. Верни только полную сигнатуру первой строки.

Функция ИмяФункции(ИмяКлиентаТестирования, ДопПараметры = Неопределено) Экспорт
	РазорватьСоединениеTestClient("ПодключитьПрофильTestClientПоИмени");

	// отключить существующий сеанс, если это не повторный запуск
	ПараметрыОтбора = Новый Структура;
	ПараметрыОтбора.Вставить("Подключен", Истина);

	НайденныеСтроки = ДанныеКлиентовТестирования.НайтиСтроки(ПараметрыОтбора);
	Если НайденныеСтроки.Количество() > 0 Тогда
		ОбъектКонтекстСохраняемый.Удалить("ТестовоеПриложение");
		ОбъектКонтекстСохраняемый.Удалить("ГлавноеОкноТестируемого");
	КонецЕсли;

	ПараметрыОтбора = Новый Структура;
	ПараметрыОтбора.Вставить("Имя", ИмяКлиентаТестирования);
	НайденныеСтроки = ДанныеКлиентовТестирования.НайтиСтроки(ПараметрыОтбора);
	Если НайденныеСтроки.Количество() = 0 Тогда
		СообщитьПользователю (ПодставитьПараметрыВСтроку(
			Локализовать("Не найден профиль клиента тестирования <%1>."),
			ИмяКлиентаТестирования
		));
		Возврат Ложь;
	КонецЕсли;

	СтрокаПрофиля = НайденныеСтроки[0];

	ЕстьПодключение = ПолучитьКлиентаТестирования(ИмяКлиентаТестирования,,,ДопПараметры);
	Если Не ЕстьПодключение Тогда
		СтрокаПрофиля.Подключен = Ложь;
	Иначе
		Для Каждого НайденнаяСтрока Из ДанныеКлиентовТестирования Цикл
			НайденнаяСтрока.Подключен = Ложь;
		КонецЦикла;

		СтрокаПрофиля.Подключен = Истина;

	КонецЕсли;

	Элементы.ДанныеКлиентовТестирования.ТекущаяСтрока = СтрокаПрофиля.ПолучитьИдентификатор();

	Возврат ЕстьПодключение;
КонецФункции

&НаКлиенте

Функция ПолучитьКлиентаТестирования(ИмяКлиентаТестирования, ДопПараметр = "", СтрокаОшибки = Неопределено,
		ДополнительныеПараметры = Неопределено) Экспорт

	Если Объект.РазрешеноЗапускатьТолькоОдинКлиентТестирования Тогда
		Если ДополнительныеПараметры = Неопределено Тогда
			ДополнительныеПараметры = Новый Структура;
		КонецЕсли;
		ДанныеЗапускаКлиентаТестирования = НайтиДанныеЗапускаКлиентаТестирования(ИмяКлиентаТестирования);
		Если ЗначениеЗаполнено(ДанныеЗапускаКлиентаТестирования.PIDКлиентаТестирования) Тогда
			ДополнительныеПараметры.Вставить("PIDПрофиляКлиентаТестированияДоЗапускаКлиентаТестирования", ДанныеЗапускаКлиентаТестирования.PIDКлиентаТестирования);
		КонецЕсли;
	КонецЕсли;

	// отключаем существующее подключение
	РазорватьСоединениеTestClient("ПолучитьКлиентаТестирования");

	ДанныеЗапускаКлиентаТестирования = НайтиДанныеЗапускаКлиентаТестирования(ИмяКлиентаТестирования);
	Если ДанныеЗапускаКлиентаТестирования = Неопределено Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(
			Локализовать("Не получилось найти данные для подключения профиля клиента тестирования <%1>"),
			ИмяКлиентаТестирования
		);
	КонецЕсли;
	ДанныеЗапускаКлиентаТестирования.ДопПараметры = ДопПараметр + ДанныеЗапускаКлиентаТестирования.ДопПараметры;
	ЕстьПодключение = ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующийДляНесколькихКлиентов(ДанныеЗапускаКлиентаТестирования,
		СтрокаОшибки, ДополнительныеПараметры);

	Если ЕстьПодключение Тогда
		Если НЕ ЗначениеПараметраЗапуска("StartFeaturePlayer", Ложь) Тогда
			СохранитьКлиентовТестирования();
		КонецЕсли;
	КонецЕсли;

	Возврат ЕстьПодключение;
КонецФункции

&НаКлиенте

Функция НайтиДанныеЗапускаКлиентаТестирования(ИмяКлиентаТестирования) Экспорт
	Результат = Неопределено;

	ПараметрыОтбора = Новый Структура;
	ПараметрыОтбора.Вставить("Имя", ИмяКлиентаТестирования);

	НайденныеСтроки = ДанныеКлиентовТестирования.НайтиСтроки(ПараметрыОтбора);
	Если НайденныеСтроки.Количество() > 0 Тогда
		Результат = НайденныеСтроки[0];
	Иначе
		ПараметрыОтбора = Новый Структура;
		ПараметрыОтбора.Вставить("Синоним", ИмяКлиентаТестирования);

		НайденныеСтроки = ДанныеКлиентовТестирования.НайтиСтроки(ПараметрыОтбора);
		Если НайденныеСтроки.Количество() > 0 Тогда
			Результат = НайденныеСтроки[0];
		КонецЕсли;
	КонецЕсли;

	Возврат Результат;
КонецФункции

// Делает переход к нужной строке таблицы
//
&НаКлиенте

Функция СделатьПереход(ТаблицаСписок, ОписаниеСтроки, ОшибкаПереходВниз, ОшибкаПереходВверх, ПереключитьВыделение = Ложь, ЗаданноеНаправление = Неопределено) Экспорт

	ПолучилосьПерейти = Ложь;

	Если ЗаданноеНаправление = Неопределено Тогда

		Попытка
			ПолучилосьПерейти = ТаблицаСписок.ПерейтиКСтроке(ОписаниеСтроки, Вычислить("НаправлениеПереходаКСтроке.Вниз"), ПереключитьВыделение);
		Исключение
			ОшибкаПереходВниз = ОписаниеОшибки();

		КонецПопытки;

		Если НЕ ПолучилосьПерейти Тогда
			Попытка
				ПолучилосьПерейти = ТаблицаСписок.ПерейтиКСтроке(ОписаниеСтроки, Вычислить("НаправлениеПереходаКСтроке.Вверх"), ПереключитьВыделение);
			Исключение
				ОшибкаПереходВверх = ОписаниеОшибки();

			КонецПопытки;
		КонецЕсли;
	Иначе

		Если ЗаданноеНаправление = "Вверх" Тогда
			ПолучилосьПерейти = ТаблицаСписок.ПерейтиКСтроке(ОписаниеСтроки, Вычислить("НаправлениеПереходаКСтроке.Вверх"), ПереключитьВыделение);
		ИначеЕсли ЗаданноеНаправление = "Вниз" Тогда
			ПолучилосьПерейти = ТаблицаСписок.ПерейтиКСтроке(ОписаниеСтроки, Вычислить("НаправлениеПереходаКСтроке.Вниз"), ПереключитьВыделение);
		Иначе
			ВызватьИсключение ПодставитьПараметрыВСтроку(Локализовать("Неверно задано направление перехода в таблице: %1"), ЗаданноеНаправление);
		КонецЕсли;

	КонецЕсли;

	Возврат ПолучилосьПерейти;

КонецФункции

// Пытается получить значение переменной из контекста
// Если значение вида $ИмяПеременной$, тогда будет возвращено ОбъектКонтекст.ИмяПеременной
// ИначеЕсли значение вида $$ИмяПеременной$$, тогда будет возвращено ОбъектКонтекстСохраняемый.ИмяПеременной
// ИначеЕсли значение вида $$$ИмяПеременной$$$, это значит, что надо отбросить $$ слева и справа, т.е. символ $ экранирован
// Иначе будет возвращено просто значение
//
&НаКлиенте

[Assistant] Функция ПодключитьПрофильTestClientПоИмени(ИмяКлиентаТестирования, ДопПараметры = Неопределено)


[System] Ты пишешь корректный код на 1С:Enterprise Script и отвечаешь только кодом, если тебя просят дописать код.

[User]
Дополни код на 1С. Ниже начало процедура `ОжиданиеОкончанияОбработки`.
Сохрани стиль и синтаксис, верни только готовый код без пояснений.

Процедура ОжиданиеОкончанияОбработки(БылаОшибка, РеквизитВыражениеВычислено)
Экспорт
	КоличествоПопытокПолученияОкнаИзПриложения = ЗначениеКоличествоПопытокВыполненияДействия();
	Для Сч = 1 По КоличествоПопытокПолученияОкнаИзПриложения Цикл
		ПредставлениеДанных = ПолучитьПредставлениеДанныхЭлементаФормы(РеквизитВыражениеВычислено);
		ПредставлениеДанных = ПривестиЗначениеФлагаКСтандарту(ПредставлениеДанных);
		Если ПредставлениеДанных <> "Да" И ПредставлениеДанных <> "Yes"
			И ПредставлениеДанных <> "Có" Тогда // vi
			sleep(1);
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ОжиданиеОкончанияОбработки(БылаОшибка, РеквизитВыражениеВычислено) Экспорт
	КоличествоПопытокПолученияОкнаИзПриложения = ЗначениеКоличествоПопытокВыполненияДействия();
	Для Сч = 1 По КоличествоПопытокПолученияОкнаИзПриложения Цикл
		ПредставлениеДанных = ПолучитьПредставлениеДанныхЭлементаФормы(РеквизитВыражениеВычислено);
		ПредставлениеДанных = ПривестиЗначениеФлагаКСтандарту(ПредставлениеДанных);
		Если ПредставлениеДанных <> "Да" И ПредставлениеДанных <> "Yes"
			И ПредставлениеДанных <> "Có" Тогда // vi
			sleep(1);
			Продолжить;
		КонецЕсли;

		БылаОшибка = Ложь;
		Прервать;
	КонецЦикла;
КонецПроцедуры

// Добавляет элемент в коллекцию ПодключенныеTestClient
&НаКлиенте

Процедура ДобавитьПодключенныйКлиентТестирования(Имя, Синоним, ТестовоеПриложение, ГлавноеОкноТестируемого, ДопПараметры) Экспорт

	Если НЕ ОбъектКонтекстСохраняемый.Свойство("ПодключенныеTestClient") Тогда
		ОбъектКонтекстСохраняемый.Вставить("ПодключенныеTestClient", Новый Массив);
	КонецЕсли;

	ОбъектКонтекстСохраняемый.ПодключенныеTestClient.Добавить(Новый Структура("Имя, Синоним, ТестовоеПриложение, ГлавноеОкноТестируемого",
	    Имя, Синоним, ТестовоеПриложение, ГлавноеОкноТестируемого));

	Если Объект.РазрешеноЗапускатьТолькоОдинКлиентТестирования И ОбъектКонтекстСохраняемый.ПодключенныеTestClient.Количество() >= 2 Тогда
		ДопПараметры.Вставить("ВызватьИсключение", Истина);
		ДопПараметры.Вставить("ТекстОшибки", Локализовать("Настройками запрещено подключать больше одного клиента тестирования одновременно.")
			 + Символы.ПС + Локализовать("Имя сценария:") + " " + ПолучитьСостояниеVanessaAutomation().ТекущийСценарий.Имя);
	ИначеЕсли Объект.РазрешеноЗапускатьТолькоОдинКлиентТестирования
			  И ДопПараметры.Свойство("PIDПрофиляКлиентаТестированияДоЗапускаКлиентаТестирования")
			  И ЗначениеЗаполнено(ДопПараметры.PIDПрофиляКлиентаТестированияДоЗапускаКлиентаТестирования)
			  Тогда

		МассивОкон1С = ПолучитьМассивPIDОкон1С();
		Для Каждого PID Из МассивОкон1С Цикл
			Если PID = ДопПараметры.PIDПрофиляКлиентаТестированияДоЗапускаКлиентаТестирования Тогда
				ДопПараметры.Вставить("ВызватьИсключение", Истина);
				ДопПараметры.Вставить("ТекстОшибки",
					Локализовать("Настройками запрещено подключать больше одного клиента тестирования одновременно.")
					+ Символы.ПС + Локализовать("Имя сценария:") + " " + ПолучитьСостояниеVanessaAutomation().ТекущийСценарий.Имя);
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

КонецПроцедуры

&НаКлиенте

Процедура ВыполнитьПроверкуСерверныхВызововВОбработчикахСобытий() Экспорт

	Если НЕ Объект.ПроверкаСерверныхВызововВОбработчикахСобытий Тогда
		Возврат;
	КонецЕсли;

	Если ТипЗнч(ОбъектКонтекстСохраняемый) <> Тип("Структура") Тогда
		Возврат;
	КонецЕсли;

	Если НЕ ОбъектКонтекстСохраняемый.Свойство("ТестовоеПриложение") Тогда
		Возврат;
	КонецЕсли;

	Если ОбъектКонтекстСохраняемый.ТестовоеПриложение = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если НЕ Объект.ИспользоватьКомпонентуVanessaExt Тогда
		ВызватьИсключение Локализовать("Необходимо включить использование внешней компоненты VanessaExt.");
	КонецЕсли;

	Если ЗапрещеныСинхронныеВызовы Тогда
		ВызватьИсключение Локализовать("Чтобы выполнить проверку серверных вызовов в обработчиках событий нужно разрешить синхронные вызовы.");
	КонецЕсли;

	Если ЭтоLinux Тогда

		КаталогКартинок = МодульОбщегоНазначенияVA().КаталогСлужебныхКартинок();

		ДанныеПодключения = ТекущиеДанныеКлиентаТестирования();
		ВнешняяКомпонентаДляСкриншотов.АктивироватьПроцесс(ДанныеПодключения.PIDКлиентаТестирования);
		Sleep(1);
		КликНаКартинкуИзБиблиотекиКартинок("Hamburger", КаталогКартинок);
		Sleep(1);
		КликНаКартинкуИзБиблиотекиКартинок("SettingsAboutTheProgram", КаталогКартинок);
		Sleep(1);

	Иначе

		PID = PIDТекущегоКлиентаТестирования();
		Если НЕ ЗначениеЗаполнено(PID) Тогда
			Возврат;
		КонецЕсли;

		ДанныеЭлементов = НайтиЭлементыПроцессаUIAutomation(PID, "Сервис и настройки", Неопределено);
		Если ДанныеЭлементов = Неопределено ИЛИ ДанныеЭлементов.Количество() = 0 Тогда
			ДанныеЭлементов = НайтиЭлементыПроцессаUIAutomation(PID, "Service and settings", Неопределено);
		КонецЕсли;
		КликПоЭлементуБезПеремещенияМышкиUIAutomation(ДанныеЭлементов[0].size, Ложь, Истина);
		Sleep(1);

		ДанныеЭлементов = НайтиЭлементыПроцессаUIAutomation(PID, "О программе...", Неопределено);
		Если ДанныеЭлементов = Неопределено ИЛИ ДанныеЭлементов.Количество() = 0 Тогда
			ДанныеЭлементов = НайтиЭлементыПроцессаUIAutomation(PID, "About...", Неопределено);
		КонецЕсли;
		КликПоЭлементуБезПеремещенияМышкиUIAutomation(ДанныеЭлементов[0].size, Ложь, Истина);
		Sleep(1);

	КонецЕсли;

	ОкноОПрограмме = Неопределено;
	Для Сч = 1 По 3 Цикл
		Попытка
			АктивноеОкно = ПолучитьАктивноеОкноИзТестовоеПриложение();
			Гиперссылка = АктивноеОкно.НайтиОбъект(,,"StaticTechInfo");
			Гиперссылка.Нажать();
			Sleep(1);
			ОкноОПрограмме = АктивноеОкно;
			Прервать;
		Исключение
		КонецПопытки;
	КонецЦикла;

	ОкноИнформацияДляТехническойПоддержки = Неопределено;
	Для Сч = 1 По 3 Цикл
		Попытка
			АктивноеОкно = ПолучитьАктивноеОкноИзТестовоеПриложение();
			ЭлементФормыСДаннымиОбОшибках = АктивноеОкно.НайтиОбъект(,,"TechInfo");
			Текст = ЭлементФормыСДаннымиОбОшибках.ПолучитьОтображаемыйТекст();
			ОкноИнформацияДляТехническойПоддержки = АктивноеОкно;
			Прервать;
		Исключение
			Sleep(1);
		КонецПопытки;
	КонецЦикла;

	ЗаписатьЛогВЖРОшибка("ВыполнитьПроверкуСерверныхВызововВОбработчикахСобытий", Текст);

	Текст = ПодготовитьТекстИсключенияПроверкиСерверныхВызововВОбработчикахСобытий(Текст);

	Если ОкноИнформацияДляТехническойПоддержки <> Неопределено Тогда
		Попытка
			ОкноИнформацияДляТехническойПоддержки.Закрыть();
			Sleep(1);
		Исключение
			ЗаписатьЛогВЖРОшибка("ВыполнитьПроверкуСерверныхВызововВОбработчикахСобытий", ОписаниеОшибки());
		КонецПопытки;
	КонецЕсли;

	Если ОкноОПрограмме <> Неопределено Тогда
		Попытка
			ОкноОПрограмме.Закрыть();
			Sleep(1);
		Исключение
			ЗаписатьЛогВЖРОшибка("ВыполнитьПроверкуСерверныхВызововВОбработчикахСобытий", ОписаниеОшибки());
		КонецПопытки;
	КонецЕсли;

	Если СтрокаСодержитТекстИсключенияПроверкиСерверныхВызововВОбработчикахСобытий(Текст) Тогда
		ВызватьИсключение Локализовать("Найдены случаи серверных вызовов в обработчиках событий:") + Символы.ПС + Текст;
	КонецЕсли;

КонецПроцедуры

&НаКлиенте

Процедура УстановитьРезультатДиалогаВыбораФайла(Результат, ИмяФайла, ИндексФильтра) Экспорт

	Если ИдетВыполнениеСценариев() Тогда
		СостояниеVanessaAutomation = ПолучитьСостояниеVanessaAutomation();
		Данные = Новый Структура;
		Данные.Вставить("ИмяФичи", СостояниеVanessaAutomation.ТекущаяФича.Имя);
		Данные.Вставить("ИмяФайлаФичи", СостояниеVanessaAutomation.ТекущаяФича.ПолныйПуть);
		Данные.Вставить("ИмяСценария", СостояниеVanessaAutomation.ТекущийСценарий.Имя);
		Данные.Вставить("ИмяШага", СостояниеVanessaAutomation.ТекущийШаг.Имя);
		Данные.Вставить("НомерСтрокиФичи", СостояниеVanessaAutomation.ТекущийШаг.НомерСтрокиФичи);
		Данные.Вставить("РезультатВыбораФайла", Результат);
		Данные.Вставить("ИмяФайла", ИмяФайла);
		Данные.Вставить("ИндексФильтра", ИндексФильтра);

		ЗаписатьЛогВЖРИнформация("УстановитьРезультатДиалогаВыбораФайла", ЗаписатьОбъектJSON(Данные));
	КонецЕсли;

	Если Версия8325ИлиВыше Тогда
		ОбъектКонтекстСохраняемый.ТестовоеПриложение.ОчиститьРезультатДиалогаВыбораФайла();
	КонецЕсли;

	Если ИндексФильтра = Неопределено Тогда
		ОбъектКонтекстСохраняемый.ТестовоеПриложение.УстановитьРезультатДиалогаВыбораФайла(Результат, ИмяФайла);
	Иначе
		ОбъектКонтекстСохраняемый.ТестовоеПриложение.УстановитьРезультатДиалогаВыбораФайла(Результат, ИмяФайла, ИндексФильтра);
	КонецЕсли;

КонецПроцедуры

// Пытается заменить колонки, указанные с символом * на реальные заголовки колонок
&НаКлиенте