Процедура ОпределитьАргументыСкрипта(Знач Стр,comand,sys_argv_1,sys_argv_2,sys_argv_3,sys_argv_4,sys_argv_5)
	Поз = Найти(Стр,"--args");
	Если Поз > 0 Тогда
		ЛеваяЧасть = УбратьКавычки(СокрЛП(Лев(Стр,Поз-1)));
		Стр = СокрЛП(Сред(Стр,Поз+6));
	Иначе
		Если ЗначениеЗаполнено(Стр) Тогда
			Стр = УбратьКавычки(Стр);
			Файл = Новый Файл(Стр);
			comand = Ванесса.Транслит(Файл.ИмяБезРасширения);
		КонецЕсли;

		Возврат;
	КонецЕсли;

	Файл = Новый Файл(ЛеваяЧасть);
	comand = Ванесса.Транслит(Файл.ИмяБезРасширения);

	НашлиПараметрВКавычках = Ложь;
	НашлиПараметр          = Ложь;

	НомерПараметра    = 0;
	ЗначениеПараметра = "";

	Для Ккк = 1 По СтрДлина(Стр) Цикл
		Символ = Сред(Стр,Ккк,1);

		Если Символ = """" И НЕ НашлиПараметрВКавычках Тогда
			НашлиПараметр = Истина;
			НашлиПараметрВКавычках = Истина;
			НомерПараметра = НомерПараметра + 1;
			ЗначениеПараметра = "";
			Продолжить;
		//ИначеЕсли Символ = " " И НЕ НашлиПараметрВКавычках Тогда
		//	НашлиПараметр = Истина;
		//	НашлиПараметрВКавычках = Ложь;
		//	НомерПараметра = НомерПараметра + 1;
		//	ЗначениеПараметра = "";
		//	Продолжить;
		КонецЕсли;

		Если НашлиПараметр Тогда
			Если НашлиПараметрВКавычках Тогда
				Если Символ = """" Тогда
					НашлиПараметрВКавычках = Ложь;
					НашлиПараметр          = Ложь;

					Если НомерПараметра = 1 Тогда
						sys_argv_1 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 2 Тогда
						sys_argv_2 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 3 Тогда
						sys_argv_3 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 4 Тогда
						sys_argv_4 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 5 Тогда
						sys_argv_5 = ЗначениеПараметра;
					КонецЕсли;
				Иначе
					ЗначениеПараметра = ЗначениеПараметра + Символ;
				КонецЕсли;
			Иначе
				Если Символ = " " Тогда
					НашлиПараметрВКавычках = Ложь;
					НашлиПараметр          = Ложь;

					Если НомерПараметра = 1 Тогда
						sys_argv_1 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 2 Тогда
						sys_argv_2 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 3 Тогда
						sys_argv_3 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 4 Тогда
						sys_argv_4 = ЗначениеПараметра;
					ИначеЕсли НомерПараметра = 5 Тогда
						sys_argv_5 = ЗначениеПараметра;
					КонецЕсли;
				Иначе
					ЗначениеПараметра = ЗначениеПараметра + Символ;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

	КонецЦикла;

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

&НаКлиенте

Процедура ЗаписатьУправляющийJson(ИмяУправляющиегоФайлаSikuliXСервер,СтрокаКоманды,comand = "")
	ВременныйJson = ПолучитьИмяВременногоФайла("json");

	ЗаписьJSON = Вычислить("Новый ЗаписьJSON()");
	ЗаписьJSON.ОткрытьФайл(ВременныйJson);

	ЗаписьJSON.ЗаписатьНачалоОбъекта();

	sys_argv_1 = "";
	sys_argv_2 = "";
	sys_argv_3 = "";
	sys_argv_4 = "";
	sys_argv_5 = "";

	ОпределитьАргументыСкрипта(СтрокаКоманды,comand,sys_argv_1,sys_argv_2,sys_argv_3,sys_argv_4,sys_argv_5);

	ЗаписьJSON.ЗаписатьИмяСвойства("comand");
	ЗаписьJSON.ЗаписатьЗначение(comand);

	ЗаписьJSON.ЗаписатьИмяСвойства("sys_argv_1");
	ЗаписьJSON.ЗаписатьЗначение(sys_argv_1);

	ЗаписьJSON.ЗаписатьИмяСвойства("sys_argv_2");
	ЗаписьJSON.ЗаписатьЗначение(sys_argv_2);

	ЗаписьJSON.ЗаписатьИмяСвойства("sys_argv_3");
	ЗаписьJSON.ЗаписатьЗначение(sys_argv_3);

	ЗаписьJSON.ЗаписатьИмяСвойства("sys_argv_4");
	ЗаписьJSON.ЗаписатьЗначение(sys_argv_4);

	ЗаписьJSON.ЗаписатьИмяСвойства("sys_argv_5");
	ЗаписьJSON.ЗаписатьЗначение(sys_argv_5);

	ЗаписьJSON.ЗаписатьКонецОбъекта();
	ЗаписьJSON.Закрыть();

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

&НаКлиенте

Функция ИмяИтогоСкрипта()
	Возврат "SikuliXServer";
КонецФункции

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

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

	УниверсальноеПолноеИмя = СтрЗаменить(ПолноеИмяФайла, "\", "/");
	Если ВНРегистр Тогда
		УниверсальноеПолноеИмя = НРег(УниверсальноеПолноеИмя);
	КонецЕсли;

	Возврат УниверсальноеПолноеИмя;
КонецФункции

&НаКлиенте

Функция УбратьКавычки(Знач Стр)
	Если Лев(Стр,1) = """" Тогда
		Стр = Сред(Стр,2);
	КонецЕсли;

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

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

&НаКлиенте

Функция ВыводКонсолиSikuliXСервер()
	Результат = "";
	ИмяФайлаВыводаКонсолиSikuliXСервер = Ванесса.ИмяФайлаВыводаКонсолиSikuliXСервер();
	Если Ванесса.ФайлСуществуетКомандаСистемы(ИмяФайлаВыводаКонсолиSikuliXСервер) Тогда
		Для Ккк = 1 По 10 Цикл
			БылаОшика = Ложь;

			Попытка
				Текст = Новый ЧтениеТекста;
				Текст.Открыть(ИмяФайлаВыводаКонсолиSikuliXСервер,"UTF-8",,, Ложь);
				Результат = Текст.Прочитать();
				Текст.Закрыть();
			Исключение
				БылаОшика = Истина;
				Ванесса.sleep(1);
			КонецПопытки;

			Если НЕ БылаОшика Тогда
				Прервать;
			КонецЕсли;

		КонецЦикла;

	КонецЕсли;

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

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


Процедура ЗапуститьБраузер(Команда)

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

	СтрокаКоманды = Ванесса.Объект.КомандаЗапускаБраузера;
	НачатьЗапускПриложения(Новый ОписаниеОповещения, СтрокаКоманды);

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

&НаКлиенте

Процедура ОшибкаБраузера(ОписаниеОшибки)

	ИнформационныйТекст =
		"Ошибка открытия браузера " + ОписаниеОшибки + "
		|закройте все открытые окна Google Chrome
		|и запустите снова кнопкой «Запустить браузер».";
	ВызватьИсключение ИнформационныйТекст;

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

&НаКлиенте

Процедура ОткрытьURL(Команда) Экспорт

	Заголовки = Новый Соответствие;
	Заголовки["Content-Type"] = "application/x-www-form-urlencoded";
	HTTPЗапрос = Новый HTTPЗапрос("/json/new?" + Ванесса.КодироватьСтрокуUrl(АдресВебКлиента), Заголовки);
	HTTPСоединение = Новый HTTPСоединение("localhost", 9222, , , , 10);
	Попытка
		HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("PUT", HTTPЗапрос);
	Исключение
		ОшибкаБраузера(ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	ТекстJSON = HTTPОтвет.ПолучитьТелоКакСтроку();

	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТекстJSON);
	ДанныеJSON = ПрочитатьJSON(ЧтениеJSON);
	АдресВебСокет = ДанныеJSON.webSocketDebuggerUrl;

	ОписаниеОповещения = Новый ОписаниеОповещения("ВызовОткрытьВебСокет", ЭтотОбъект);
	Ванесса.ВнешняяКомпонентаДляСкриншотов.НачатьВызовОткрытьВебСокет(ОписаниеОповещения, АдресВебСокет);

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

&НаКлиенте

Процедура ВыполнитьJavaSctipt(Команда) Экспорт

	Ванесса.ЗапретитьВыполнениеШагов();

	ПараметрыМетода = Новый Структура("expression", ТекстJavaScript);
	ДанныеJSON = Новый Структура("id,method,params", 1, "Runtime.evaluate", ПараметрыМетода);
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, ДанныеJSON);
	КомандаJSON = ЗаписьJSON.Закрыть();

	ДанныеШага = Новый Структура("ТекстJavaScript,КомандаШага",ТекстJavaScript,КомандаШага);
	ОписаниеОповещения = Новый ОписаниеОповещения("ВызовJavaSctipt", ЭтотОбъект, ДанныеШага);
	Ванесса.ВнешняяКомпонентаДляСкриншотов.НачатьВызовПослатьВебСокет(ОписаниеОповещения, КомандаJSON);

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

&НаКлиенте

Процедура СнимокЭкранаБраузера(Команда) Экспорт

	ПараметрыМетода = Новый Структура("format,quality,fromSurface", "png", 85, Ложь);
	ДанныеJSON = Новый Структура("id,method,params", 1, "Page.captureScreenshot", ПараметрыМетода);

	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, ДанныеJSON);
	КомандаJSON = ЗаписьJSON.Закрыть();

	ОписаниеОповещения = Новый ОписаниеОповещения("ПолученСнимокБраузера", ЭтотОбъект);
	Ванесса.ВнешняяКомпонентаДляСкриншотов.НачатьВызовВебСокет(ОписаниеОповещения, АдресВебСокет, КомандаJSON);

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

&НаКлиенте

Процедура ПоказатьКомандыЭлементаБраузера(Команда)

	ТекстHTMLТекущийЭлементОбновить(Элементы.ТекстHTML.Документ.activeElement);
	Если Элементы.ГруппаКомандыБраузер.Видимость Тогда
		Элементы.ГруппаКомандыБраузер.Показать();
	КонецЕсли;

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

&НаКлиенте

Процедура ПоказатьКодHTML(Команда)
	ТекстовоеПоле = Новый ТекстовыйДокумент;
	ТекстовоеПоле.УстановитьТекст(Элементы.ТекстHTML.Документ.documentElement.innerHTML);
	ТекстовоеПоле.Показать("Код страницы");
КонецПроцедуры

&НаКлиенте

Процедура КомандаБраузераВБуфер(Команда)

	Если Не ПустаяСтрока(КомандаБраузера) Тогда
		Ванесса.ПоместитьВБуферОбменаVA(КомандаБраузера);
		Сообщить("Скопировано в буфер обмена")
	КонецЕсли;

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

&НаКлиенте

Процедура КомандаЭлементБраузераВБуфер(Команда)

	Если Элементы.КомандыЭлементаБраузера.ТекущиеДанные <> Неопределено Тогда
		Ванесса.ПоместитьВБуферОбменаVA(Элементы.КомандыЭлементаБраузера.ТекущиеДанные.Значение);
		Сообщить("Скопировано в буфер обмена")
	КонецЕсли;

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

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

#Область ОбработчикиСобытийФормы

&НаКлиенте

Процедура ПриОткрытии(Отказ)

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

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	ПортБраузера = 9222;

	ТочкаX = 200;
	ТочкаY = 200;
	Width = 600;
	Height = 300;
	НадписьТекст = "Для оплаты нажать ====>";

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

&НаКлиенте

Процедура ТекстHTMLПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	ТекстHTMLТекущийЭлементОбновить(ДанныеСобытия.Element);

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

&НаКлиенте

Процедура ТекстHTMLПриИзменении(Элемент)

	ТекстHTMLТекущийЭлементОбновить(Элементы.ТекстHTML.Документ.activeElement);

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

&НаКлиенте

Процедура ФигурыПриИзменении(Элемент)

	Если ТипФигуры = "Надпись" Тогда

		Width = 0;
		Height = 0;
		Элементы.Width.Видимость = Ложь;
		Элементы.Height.Видимость = Ложь;
		Элементы.НадписьТекст.Видимость = Истина;

		ТекстШаблона = "{
		|    let node = document.createElement('div');
		|    node.innerHTML =
		|    '%НадписьТекст%';
		|    node.style.fontSize = '100%';
		|    node.style.position = 'fixed';
		|    node.style.zIndex = 999999;
		|    node.style.left = '%ТочкаX%px';
		|    node.style.top = '%ТочкаY%px';
		|    node.style.color = 'red';
		|    node.style.backgroundColor = '#11ffee00';
		|    node.style.padding = '1em';
		|    window.top.document.body.appendChild(node);
		|    setTimeout(() => { if (node) node.remove() }, 10000);
		|};";
		ПараметрыОтрисовки = Новый Структура("ТочкаX,ТочкаY,НадписьТекст", ТочкаX,ТочкаY,НадписьТекст);

	Иначе

		Элементы.Width.Видимость = Истина;
		Элементы.Height.Видимость = Истина;
		Элементы.НадписьТекст.Видимость = Ложь;

		ТекстШаблона = "{
		|    let node = document.createElement('div');
		|    node.style.fontSize = '100%';
		|    node.style.position = 'fixed';
		|    node.style.zIndex = 999999;
		|    node.style.left = '%ТочкаX%px';
		|    node.style.top = '%ТочкаY%px';
		|    node.style.width = '%Width%px';
		|    node.style.height = '%Height%px';
		|    node.style.borderWidth = '0.1em';
		|    node.style.borderStyle = 'solid';
		|    node.style.borderColor = 'red';
		|    node.style.backgroundColor = '#11ffee00';
		|    node.style.padding = '1em';
		|    node.style.borderRadius = '1em';
		|    window.top.document.body.appendChild(node);
		|    setTimeout(() => { if (node) node.remove() }, 10000);
		|};";
		ПараметрыОтрисовки = Новый Структура("ТочкаX,ТочкаY,Width,Height", ТочкаX,ТочкаY,Width,Height);

	КонецЕсли;

	ТекстJavaScript = ТекстШаблона;

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

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

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

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

&НаКлиенте


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

	Если (Лев(Значение, 3) = "$$$") И (Прав(Значение, 3) = "$$$") Тогда
		// это значит, что надо отбросить $$ слева и справа
		Значение = Сред(Значение, 3);
		Возврат Лев(Значение, СтрДлина(Значение) - 2);

	ИначеЕсли Лев(Значение, 2) = "$$" И Прав(Значение, 2) = "$$" Тогда

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

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

		Если ЕстьТакаяПеременная Тогда
			Возврат ОбъектКонтекстСохраняемый[ИмяПеременной];
		КонецЕсли;

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

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

	Иначе

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

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

		Если ЕстьТакаяПеременная Тогда
			Возврат ОбъектКонтекст[ИмяПеременной];
		КонецЕсли;

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

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

	КонецЕсли;

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

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

Функция ЗначениеПеременной(Знач ИмяПеременной) Экспорт
	Попытка
		Значение = ПолучитьЗначениеИзКонтекстаЕслиЭтоВозможно(ИмяПеременной);
	Исключение
		Значение = Неопределено;
	КонецПопытки;

	Если Значение <> Неопределено И Значение <> ИмяПеременной Тогда
		Возврат Значение;
	КонецЕсли;

	Попытка
		Значение = ПолучитьЗначениеИзКонтекстаЕслиЭтоВозможно("$" + ИмяПеременной + "$");
	Исключение
		Значение = Неопределено;
	КонецПопытки;

	Если Значение <> Неопределено И Значение <> ИмяПеременной Тогда
		Возврат Значение;
	КонецЕсли;

	Попытка
		Значение = ПолучитьЗначениеИзКонтекстаЕслиЭтоВозможно("$$" + ИмяПеременной + "$$");
	Исключение
		Значение = Неопределено;
	КонецПопытки;

	Если Значение <> Неопределено И Значение <> ИмяПеременной Тогда
		Возврат Значение;
	КонецЕсли;

	Возврат Неопределено;

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

&НаКлиенте

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

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

	ОписаниеСтроки = Новый Соответствие();

	Строка1    = ТабПарам[0];
	Строка2    = ТабПарам[1];
	КолКолонок = Строка1.Количество();

	Для Ккк = 1 По КолКолонок Цикл
		Если ИсключитьКолонку = Ккк Тогда
			Продолжить;
		КонецЕсли;

		Ключ = Строка1["Кол" + Формат(Ккк, "ЧГ=; ЧН=0")];

		НеобходимПоискКлючаПоШаблону = СравнениеПоШаблону
										И ТаблицаКлиентаТестирования <> Неопределено
										И ТаблицаКлиентаТестирования.Количество() > 0
										И Найти(Ключ, "*") > 0;
		Если НеобходимПоискКлючаПоШаблону  Тогда
			Для Каждого ДанныеПервойСтроки Из ТаблицаКлиентаТестирования[0] Цикл
				Если СтрокаСоответствуетШаблону(ДанныеПервойСтроки.Ключ, Ключ) Тогда
					Ключ = ДанныеПервойСтроки.Ключ;
					Прервать;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;

		Если Найти(Ключ, "\n") > 0 Тогда
			ПереводСтроки = Истина;
			Если ТипЗнч(ДопПараметры) = Тип("Структура") И ДопПараметры.Свойство("ПереводСтроки") Тогда
				ПереводСтроки = ДопПараметры.ПереводСтроки;
			КонецЕсли;

			СтрокаЗаменыПереводаСтроки = Символы.ПС;
			Если НЕ ПереводСтроки Тогда
				СтрокаЗаменыПереводаСтроки = Символы.ВК + СтрокаЗаменыПереводаСтроки;
			КонецЕсли;
			Ключ = СтрЗаменить(Ключ, "\n", СтрокаЗаменыПереводаСтроки);

			Если ТипЗнч(ДопПараметры) = Тип("Структура") Тогда
				ДопПараметры.Вставить("ПереводСтроки", НЕ ПереводСтроки);
			КонецЕсли;
		КонецЕсли;
		Значение = Строка2["Кол" + Формат(Ккк, "ЧГ=; ЧН=0")];
		Если ТипЗнч(Значение) = Тип("Число") Тогда
			Значение = СтрЗаменить(Значение, Символы.НПП, "");
		КонецЕсли;

		Значение = СтрЗаменить(Значение, "\n", Символы.ПС);

		Если ЗаменятьИмяКолонки Тогда
			ОбходОшибкиПустойКлюч = ИмяТаблицы = "TypeTree" И Ключ = "Значение"
								ИЛИ ИмяТаблицы = "TypeTree" И Ключ = "Колонка1" И НЕ (ТекущийTestclientЭтоWebКлиент);
			Если ОбходОшибкиПустойКлюч Тогда
				// Обход бага разного представления таблицы выбора типа в тонком клиенте и в web клиенте
				Ключ = "";
			ИначеЕсли ИмяТаблицы = "ValueList" И Ключ = "" Тогда
				// Обход бага разного представления таблицы выбора типа в тонком клиенте и в web клиенте
				Ключ = "Значение";
			КонецЕсли;
		КонецЕсли;

		ОписаниеСтроки.Вставить(Ключ, Значение);
	КонецЦикла;

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

&НаКлиенте

Процедура АктивизироватьЭлементформы(ЭлементФормы) Экспорт
	Попытка
		ЭлементФормы.Активизировать();
	Исключение
	КонецПопытки;
КонецПроцедуры

&НаКлиенте


Процедура ПрочитатьИзФичиПараметрыСборкиВидео()
	Если Объект.РежимВыполненияОдногоШага Тогда
		Возврат;
	КонецЕсли;
	//+++ ЦВ_ПР 31.10.2025 Необходимо "Обрезать фичу" Сверху (если задан режим с текущего шага.. и до шага принудительной остановки сценариев, если таковой будет обнаружен)
	ПринудительнаяОстановкаСценария = Ложь;
	НайденШагЗапускаТеста = Ложь;
    НовыйМассивСценариев = Новый Массив;
	//+++ Определяем индекс текущего сценария для ГлубокоеКопирование
	ТекИД_СценарияВМассиве = -1;
    //--- ЦВ_ПР 31.10.2025

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

		НайтиПризнакЧтоСценарийНадоИгнорировать(МассивФичи, Сценарий);
		НайтиПризнакЧтоСлайдСценарияНадоИгнорировать(МассивФичи, Сценарий);

		Шаги       = Сценарий.Шаги;
		//+++ ЦВ_ПР 22.10.2025 Необходими "Обрезать фичу" до шага принудительной остановки сценариев, если таковой будет обнаружен
		ИндексШагаОстановки = -1;
		НовыйМассивШагов = Новый Массив;
		//Определяем индекс текущего сценария для функции ГлубокоеКопирование
		ТекИД_СценарияВМассиве = ТекИД_СценарияВМассиве + 1;
		//--- ЦВ_ПР 22.10.2025
    	ЗначениеТегаStartStopRecordVideo = Неопределено;  //+++ ЦВ_ПР 27.10.2025 Для управления директивным началом и окончанием записи Видео тегом StartRecordVideo и StopRecordVideo

		Для Каждого Шаг Из Шаги Цикл
			//+++ ЦВ_ПР 31.10.2025  Обрезка массива сверху с учетом параметров выполнения с Текущего шага...
			Если НЕ НайденШагЗапускаТеста
				И (Объект.РежимВыполненияДанногоСценарияСТекущегоШага ИЛИ Объект.РежимВыполненияДанногоСценарияСТекущегоШагаСПродолжением) Тогда
    			Если Шаг.СтрокаШага < МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИдСтрокиШагаСКоторогоВыполнятьСценарийСДанногоШага Тогда
                    Продолжить;
				КонецЕсли;
				НайденШагЗапускаТеста = Истина;
			КонецЕсли;
			//--- ЦВ_ПР 31.10.2025

			//+++ ЦВ_ПР 27.10.2025 Для управления директивным началом и окончанием записи Видео тегом StartRecordVideo и StopRecordVideo
			Если НЕ Объект.ЗаписьВидеоГруппаШаговКакШаг Тогда
               // Заполним здесь, если нет признака, Для группы шагов будет отдельная обработка,
				ЗначениеТегаStartStopRecordVideo =?(ЭтотШагНеИгнорироватьДляВидеоИнструкции(Шаг) ИЛИ (Шаг.Свойство("ПервыйВГруппеШагов") и Шаг.ПервыйВГруппеШагов),"Start",ЗначениеТегаStartStopRecordVideo);
				Если ШагИмеетТег(Шаг,"StartRecordVideo") Тогда
					Шаг.Вставить("ДирективныйЗапускЗаписиВидео", Истина);
					ЗначениеТегаStartStopRecordVideo = "Start";
				ИначеЕсли ШагИмеетТег(Шаг,"StopRecordVideo") Тогда
					Шаг.Вставить("ДирективныйОстановЗаписиВидео", Истина);
					ЗначениеТегаStartStopRecordVideo = "Stop";
				КонецЕсли;
				Шаг.Вставить("RecordVideo",ЗначениеТегаStartStopRecordVideo);
			КонецЕсли;
			//--- ЦВ_ПР 27.10.2025 конец вставки

			//+++ ЦВ_ПР 24.11.2025 Обрабатываем шаги до 1-го шага остановки выполнение сценариев данной фичи, дальнейшие шаги не выполняем
			ИндексШагаОстановки = ИндексШагаОстановки +1;
			Если Шаг.СтрокаРеальнойПроцедуры = "ЯОстанавливаюВыполнениеСценариевДаннойФичи" Тогда
				ПринудительнаяОстановкаСценария = Истина;
				Шаг.Вставить("ИдСледующегоШага", Неопределено);
				НовыйМассивШагов.Добавить(ГлубокоеКопирование(Шаг, Ложь));
				Прервать;
			КонецЕсли;
            //--- ЦВ_ПР 24.11.2025

			Если Шаг.Свойство("ЭтоШагКонтекста") И Шаг.ЭтоШагКонтекста Тогда
				НовыйМассивШагов.Добавить(ГлубокоеКопирование(Шаг, Ложь));
				Продолжить;
			КонецЕсли;

			НайтиГруппыШаговКоторыеНадоОбрабатыватьКакОдинШаг(МассивФичи, Шаг, Сценарий);
			НайтиГруппыШаговКоторыеНадоИгнорировать(МассивФичи, Шаг, Сценарий);

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

		КонецЦикла;
		//+++ ЦВ_ПР 25.06.2025 Почистим окно сообщений
		СостояниеСВидео(Истина,"",,);
		//--- ЦВ_ПР 25.06.2025 конец вставки
		//+++ ЦВ_ПР 31.10.2025 Если Начинали с текущего шага не в 1-м сценарии, то ничего не пишем в новый Массив
		Если НЕ НайденШагЗапускаТеста И (Объект.РежимВыполненияДанногоСценарияСТекущегоШага ИЛИ Объект.РежимВыполненияДанногоСценарияСТекущегоШагаСПродолжением) Тогда
           Продолжить;
   		КонецЕсли;
		// Создаем обрезанный сценарий сразу с нужными шагами
		НовыйСценарий = ГлубокоеКопирование(Сценарий, Ложь);
		НовыйСценарий.Шаги = НовыйМассивШагов;
		Если НовыйМассивШагов.Количество() > 0 Тогда
   			НовыйМассивСценариев.Добавить(НовыйСценарий);
		КонецЕсли;
		Если ПринудительнаяОстановкаСценария Тогда
			Прервать;
   		КонецЕсли;
        //--- ЦВ_ПР 31.10.2025
	КонецЦикла;
	//+++ ЦВ_ПР 31.10.2025 Уточнение. Обрабатываем шаги до 1-го шага остановки выполнение сценариев или с указанного шага
	Если ПринудительнаяОстановкаСценария ИЛИ НайденШагЗапускаТеста Тогда
    // Заменяем исходный массив
	    МассивСценариевДляВыполнения = НовыйМассивСценариев;
	КонецЕсли;
	//--- ЦВ_ПР 31.10.2025

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

&НаКлиенте

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

&НаКлиенте

Процедура ПроставитьСвойстваШагаСУчетомСвойствГруппы(Шаг, СтрокаДереваШаг, Сценарий)
	ШагНадоИгнорировать = Ложь;
	ТекСтрока = СтрокаДереваШаг;
	Пока Истина Цикл
		РодительШага     = ТекСтрока.ПолучитьРодителя();
		ЭлементыРодителя = РодительШага.ПолучитьЭлементы();

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

							СлужебнаяСтрока = СокрЛП(РодительШага.Имя);
							Если Найти(НРег(Комментарий), "#[autodoc.groupsteps]") > 0 Тогда
								//Особенность старого парсера
								ПромСтрока = Сред(СокрЛП(Комментарий), 22);
							Иначе
								ПромСтрока = Сред(СокрЛП(Комментарий), 21);
							КонецЕсли;
							Если ЗначениеЗаполнено(ПромСтрока) Тогда
								СлужебнаяСтрока = ПромСтрока;
							КонецЕсли;

							Индекс = ЭлементыРодителя.Индекс(СтрокаДереваШаг);
							Если Индекс <> (ЭлементыРодителя.Количество() - 1) Тогда
								// вызываем проверку только для одного шага
								ШагНадоИгнорировать = Истина;
								Прервать;
							КонецЕсли;

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

							ОбработатьУправляющуюСтрокуИнструкции(СлужебнаяСтрока, ПараметрыОбработки);

							Шаг.Вставить("ТекстИнструкция", СокрЛП(СлужебнаяСтрока));
						ИначеЕсли Найти(НРег(Комментарий), "[autodoc.ignorestep]") > 0 Тогда
							ШагНадоИгнорировать = Истина;
							Прервать;
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

		ТекСтрока = РодительШага;
	КонецЦикла;

	Шаг.Вставить("ИгнорироватьШагВАвтоинструкции", ШагНадоИгнорировать);
КонецПроцедуры

&НаКлиенте


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

&НаКлиенте

Процедура НайтиСтрокуТаблоРекурсивно(ЭлементыТабло, Имя, ИсточникДанных, НужнаяСтрока)
	Для Каждого СтрокаЭлементыТабло Из ЭлементыТабло Цикл
		Если НужнаяСтрока <> Неопределено Тогда
			Прервать;
		КонецЕсли;

		Если СтрокаЭлементыТабло.Имя = Имя И СтрокаЭлементыТабло.ИсточникДанных = ИсточникДанных Тогда
			НужнаяСтрока = СтрокаЭлементыТабло;
			Прервать;
		КонецЕсли;

		НайтиСтрокуТаблоРекурсивно(СтрокаЭлементыТабло.ПолучитьЭлементы(), Имя, ИсточникДанных, НужнаяСтрока);
	КонецЦикла;
КонецПроцедуры

&НаКлиенте

Процедура РазвернутьСвернутьСтрокиТаблоПеременных()
	Если НЕ Элементы.ГруппаПросмотрПеременных.Видимость Тогда
		Возврат;
	КонецЕсли;

	СтрокиТаблоПеременных = ТаблоПеременных.ПолучитьЭлементы();
	Если СтрокиТаблоПеременных.Количество() > 0 Тогда
		СтрокаТабло = СтрокиТаблоПеременных[0];
		ИдентификаторСтроки = СтрокаТабло.ПолучитьИдентификатор();
		Элементы.ТаблоПеременных.Развернуть(ИдентификаторСтроки, Истина);

		Для Каждого ПодчиненнаяСтрока Из СтрокиТаблоПеременных[0].ПолучитьЭлементы() Цикл
			ИдентификаторСтроки = ПодчиненнаяСтрока.ПолучитьИдентификатор();
			Элементы.ТаблоПеременных.Свернуть(ИдентификаторСтроки);
		КонецЦикла;

		Для Каждого ПодчиненнаяСтрока Из СтрокиТаблоПеременных[1].ПолучитьЭлементы() Цикл
			ИдентификаторСтроки = ПодчиненнаяСтрока.ПолучитьИдентификатор();
			Элементы.ТаблоПеременных.Свернуть(ИдентификаторСтроки);
		КонецЦикла;

	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ЗаполнитьИменаСлужебныхПеременныхКонтекста()

	СлужебныеПеременныеКонтекста = Новый Соответствие;
	СлужебныеПеременныеКонтекста.Вставить("АктивнаяТаблицаTestClient", Истина);
	СлужебныеПеременныеКонтекста.Вставить("АктивноеОкно", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ЗавершитьВыполнениеЦикла", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ТекущаяТЧ", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ТекущийВыпадающийСписок", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ПредыдущееАктивноеОкно", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ТестовоеПриложение", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ГлавноеОкноТестируемого", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ТекущийПрофильTestClient", Истина);
	СлужебныеПеременныеКонтекста.Вставить("ПодключенныеTestClient", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ДанныеФайловПриСохраненииМакета", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ЭлементФормы", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ОтборЭлементов", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ПодсказкаЭлементаФормы", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_СостоянияOnboarding", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ЗаголовокОкнаOnboarding", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ИмяЭлементаФормы", Истина);
	СлужебныеПеременныеКонтекста.Вставить("КешДанныхФормOnboarding", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ТекущееСостояниеOnboarding", Истина);
	СлужебныеПеременныеКонтекста.Вставить("_ЭлементUIAutomationOnboarding", Истина);

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

&НаКлиенте

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

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

Функция ПреобразоватьКДатеСтрокуКакСтроку(Знач Стр)
	Возврат "'" + Формат(ПреобразоватьСтрокуВДату(Стр), "ДФ=yyyyMMdd; ДП=00010101") + "'";
КонецФункции

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

Функция ПреобразоватьСтрокуВДату(Знач Стр)
	НачСтр = Стр;

	Год   = 0;
	Год2000 = 2000;
	Век = 100;
	Месяц = 0;
	День  = 0;

	Поз  = Найти(Стр, ".");
	День = Число(Лев(Стр, Поз - 1));
	Стр = Сред(Стр, Поз + 1);

	Поз   = Найти(Стр, ".");
	Месяц = Число(Лев(Стр, Поз - 1));
	Стр   = Сред(Стр, Поз + 1);

	Год   = Число(Стр);
	Если СтрДлина(Стр) = 2 И Год < Век Тогда
		Год = Год + Год2000;
	КонецЕсли;

	Возврат Дата(Год, Месяц, День);
КонецФункции

&НаСервере

Функция VAОткрытаКакВнешняяОбработка(ОбъектНаСервере)
    ПолноеИмяМетаданных = ОбъектНаСервере.Метаданные().ПолноеИмя();
    Возврат Метаданные.НайтиПоПолномуИмени(ПолноеИмяМетаданных) = Неопределено;
КонецФункции

&НаКлиенте

Функция СтруктураОшибкиVA()
	Возврат Новый Структура("ОшибкаAssert,ЗначениеActual,ЗначениеExpected", Ложь, Неопределено, Неопределено);
КонецФункции

&НаКлиенте

Процедура ЗаполнитьЗначенияПоУмолчанию1СTTS()

	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидео1СГолос) Тогда
		Объект.ЗаписьВидео1СГолос = "Ирина";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидео1ССкоростьРечи) Тогда
		Объект.ЗаписьВидео1ССкоростьРечи = 1.1;
	КонецЕсли;

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

&НаКлиенте

Процедура ЗаполнитьЗначенияПоУмолчаниюYandexTTS()
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоYandexTTSЯзык) Тогда
		Объект.ЗаписьВидеоYandexTTSЯзык = "ru-RU";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоYandexTTSГолос) Тогда
		Объект.ЗаписьВидеоYandexTTSГолос = "oksana";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоYandexTTSЭмоция) Тогда
		Объект.ЗаписьВидеоYandexTTSЭмоция = "good";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоYandexTTSСкорость) Тогда
		Объект.ЗаписьВидеоYandexTTSСкорость = 1.1;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ЗаполнитьЗначенияПоУмолчаниюAmazonTTS()
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоAmazonГолос) Тогда
		Объект.ЗаписьВидеоAmazonГолос = "en-US";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоAmazonДвижок) Тогда
		Объект.ЗаписьВидеоAmazonДвижок = "standard";
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоAmazonЯзык) Тогда
		Объект.ЗаписьВидеоAmazonЯзык = "Aditi";
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ЗаполнитьЗначенияПоУмолчаниюСберTTS()

	Если НЕ ЗначениеЗаполнено(Объект.ЗаписьВидеоСберTTSГолос) Тогда
		Объект.ЗаписьВидеоСберTTSГолос = "Nec_24000";
	КонецЕсли;

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

&НаКлиенте

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

&НаКлиенте

Функция ОпределитьЯзыкЗапуска(ТекущийЯзык, ДопПараметры)
	Поз1 = Найти(ДопПараметры, "/L ");
	ПромСтрока = Сред(ДопПараметры, Поз1 + 3);
	Поз2 = Найти(ПромСтрока, "/L ");

	ЧислоВхожденийЯзыковогоПараметра = СтрЧислоВхождений(ДопПараметры, "/L ");
	Если (Поз1 > 0) И (Поз2 > 0) Тогда
		СообщитьПользователю(Локализовать("Обнаружен больше чем 1 параметр L"));
		Возврат ДопПараметры;
	ИначеЕсли (Поз1 > 0) И (Поз2 = 0) Тогда
		ПозицияЯзыковогоПараметра = Найти(ДопПараметры, "/L ");
		ЯзыкСтрока = Сред(ДопПараметры, ПозицияЯзыковогоПараметра + 3, 2);
		ДопПараметрыСНовымЯзыком = СтрЗаменить(ДопПараметры, ЯзыкСтрока, ТекущийЯзык);
		Возврат ДопПараметрыСНовымЯзыком;
	Иначе
		ДопПараметры =  ДопПараметры + " /L " + ТекущийЯзык;
		Возврат ДопПараметры;
	КонецЕсли;
КонецФункции

&НаКлиенте


Процедура ДобавитьОписаниеСтраницыВНастройкиЗапуска(СтраницаФормы, МассивСтрок, Уровень, ИменаПолейJson)
	Для Каждого ТекЭлемент Из СтраницаФормы.ПодчиненныеЭлементы Цикл

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

			КонецЕсли;

			Если УказанЗаголовок Тогда
				ДобавитьОписаниеСтраницыВНастройкиЗапуска(ТекЭлемент, МассивСтрок, Уровень + 1, ИменаПолейJson)
			Иначе
				ДобавитьОписаниеСтраницыВНастройкиЗапуска(ТекЭлемент, МассивСтрок, Уровень, ИменаПолейJson)
			КонецЕсли;

		Иначе
			Если ТипЗнч(ТекЭлемент) = Тип("КнопкаФормы") Тогда
				Продолжить;
			КонецЕсли;

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

			Если НЕ ПустаяСтрока(ТекЭлемент.РасширеннаяПодсказка.Заголовок) Тогда
				ИмяНастройки = ИмяНастройкиПоИмениЭлемента(ТекЭлемент.Имя, ИменаПолейJson);
				Если ИмяНастройки = Неопределено Тогда
					Продолжить;
				КонецЕсли;

				СтрокаПараметра = СимволыГруппыРазметки(Уровень + 1) + "**" + ИмяНастройки + "**:";
				МассивСтрок.Добавить(СтрокаПараметра);
				ДанныеОписания = ОписаниеПоПодсказкеЭлемента(ТекстПодсказки, СтрокаПараметра);
				Для Каждого ТекСтрока Из ДанныеОписания Цикл
					МассивСтрок.Добавить(СгенерироватьСтрокуПробелов((Уровень+2)*3) + ТекСтрока);
				КонецЦикла;
				Если МассивСсылок <> Неопределено Тогда
					Для Каждого Стр Из МассивСсылок Цикл

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

						Если Нашли Тогда
							Продолжить;
						КонецЕсли;

						МассивСтрок.Добавить(СгенерироватьСтрокуПробелов((Уровень+2)*3) + Стр);
					КонецЦикла;
				КонецЕсли;
				МассивСтрок.Добавить("");
			КонецЕсли;
		КонецЕсли;

	КонецЦикла;
КонецПроцедуры

&НаКлиенте

Функция ПолучитьСсылкиИзФорматированнойСтроки(ФорматированнаяСтрока)

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

	Если ТипЗнч(ФорматированнаяСтрока) = Тип("Строка") Тогда
		Возврат Результат;
	КонецЕсли;

	Док = Новый ФорматированныйДокумент;
    Док.УстановитьФорматированнуюСтроку(ФорматированнаяСтрока);

    ТекстHTML = Неопределено;
    Вложения = Неопределено;
    Док.ПолучитьHTML(ТекстHTML, Вложения);

	МассивСтрок = _СтрРазделить(ТекстHTML, Символы.ПС);
	Для Сч = 0 По МассивСтрок.Количество()-1 Цикл
		Стр = МассивСтрок[Сч];

		Поз = Найти(Стр, "href=");
		Если Поз > 0 Тогда
			Стр = Сред(Стр, Поз);
			Стр = СтрЗаменить(Стр, "href=", "");
			Стр = Сред(Стр, 2); //Убрали кавычку
			Поз2 = Найти(Стр, ">");
			Поз3 = Найти(Стр, """");
			Поз2 = Мин(Поз2,Поз3);
			Стр = Лев(Стр, Поз2 - 1);
			Стр = СтрЗаменить(Стр, """", "");
			Если ЗначениеЗаполнено(Стр) И Найти(НРег(Стр), "http") > 0 Тогда
				Результат.Добавить(Стр);
			КонецЕсли;
		КонецЕсли;

	КонецЦикла;

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

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

&НаКлиенте

Процедура УГруппыЕстьПодчиненныеПоляРекурсивно(ТекГруппа, КолПолей)

	Для Каждого Элем Из ТекГруппа.ПодчиненныеЭлементы Цикл
		Если ТипЗнч(Элем) = Тип("КнопкаФормы") Тогда
			Продолжить;
		ИначеЕсли ТипЗнч(Элем) = Тип("ГруппаФормы") Тогда
			УГруппыЕстьПодчиненныеПоляРекурсивно(Элем, КолПолей);
			Продолжить;
		КонецЕсли;

		КолПолей = КолПолей + 1;

	КонецЦикла;

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

&НаКлиенте

Функция УГруппыЕстьПодчиненныеПоля(ТекГруппа)
	КолПолей = 0;
	УГруппыЕстьПодчиненныеПоляРекурсивно(ТекГруппа, КолПолей);

	Если КолПолей > 0 Тогда
		Возврат Истина;
	Иначе
		Возврат Ложь;
	КонецЕсли;

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

&НаКлиенте

Функция СгенерироватьСтрокуПробелов(Кол)

	Стр = "";
	Для Сч = 1 По Кол Цикл
		Стр = Стр + " ";
	КонецЦикла;

	Возврат Стр;

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

&НаКлиенте

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

	ТипОбъектаПоиска = Тип("ТестируемаяКнопкаФормы");
	ИмяОбъектаПоиска = "Обновить";

	ТаблицаОбновлена = НайтиИНажатьКнопкуОбновленияТаблицы(
		ТестируемаяТаблицаФормы,
		ДопПараметры,
		ТипОбъектаПоиска,
		ИмяОбъектаПоиска);

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

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

&НаКлиенте

Функция НайтиИНажатьКнопкуОбновленияТаблицы(ТестируемаяТаблицаФормы, ДопПараметры, ТипОбъектаПоиска, ИмяОбъектаПоиска)

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

	// Способ поиска кнопки Обновить в панелях формы используем для форм генириуемых по умолчанию платформой.
	Если КнопкаОбновить = Неопределено
		И ТипЗнч(ДопПараметры) = Тип("Структура")
		И ДопПараметры.Свойство("ФормаРеквизита")
		И ТипЗнч(ДопПараметры.ФормаРеквизита) = Тип("ТестируемаяФорма") Тогда

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

	КонецЕсли;

	Если КнопкаОбновить <> Неопределено Тогда
		КнопкаОбновить.Нажать();
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;

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

&НаКлиенте

Процедура ЗаписатьВЖРДанныеОНастройкахVanessaAutomation()
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("НастройкиВыгрузки", Истина);
	ДопПараметры.Вставить("ВыгружатьЭтотКлиент", Истина);

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

	ТекущийЯзык = Объект.ЯзыкГенератораGherkin;

	ЗаписатьЛогВЖРИнформация("VASettings",ПодготовитьОбщиеНастройкиКВыгрузке(Настройки, ТекущийЯзык));
КонецПроцедуры

&НаКлиенте


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

	МассивСтрок = _СтрРазделить(Стр, Символы.ПС);
	НовыйМассивСтрок = Неопределено;
	Для Сч = 0 По МассивСтрок.Количество()-1 Цикл
		ТекСтр = МассивСтрок[Сч];
		Если ТекСтр = "Ошибки:" Тогда
			НовыйМассивСтрок = Новый Массив;
			Для Сч2 = Сч + 1 По МассивСтрок.Количество()-1 Цикл
				НовыйМассивСтрок.Добавить(МассивСтрок[Сч2]);
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;

	Если НовыйМассивСтрок = Неопределено Тогда
		НовыйМассивСтрок = МассивСтрок;
	КонецЕсли;

	Спс = Новый СписокЗначений;
	Кеш = Новый Соответствие;
	Для Сч = 0 По НовыйМассивСтрок.Количество() - 1 Цикл
		ТекСтр = НовыйМассивСтрок[Сч];

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

		Если Кеш[ТекСтр] <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		Кеш.Вставить(ТекСтр, Истина);

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

	Спс.СортироватьПоЗначению();

	Если Спс.Количество() = 0 Тогда
		Возврат "";
	КонецЕсли;

	Возврат _СтрСоединить(Спс.ВыгрузитьЗначения(), Символы.ПС);

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

&НаКлиенте

Функция ТабличыйДокументПоМассивуМассивов(Массив)

	ТабДок = Новый ТабличныйДокумент;

	СчСтрок = 0;
	Для Каждого ТекСтрока Из Массив Цикл
		СчСтрок = СчСтрок + 1;
		СчКолонок = 0;
		Для Каждого ТекЗначение Из ТекСтрока Цикл
			СчКолонок = СчКолонок + 1;
			ТабДок.Область(СчСтрок,СчКолонок,СчСтрок,СчКолонок).Текст = ТекЗначение;
		КонецЦикла;
	КонецЦикла;

	Возврат ТабДок;

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

&НаКлиенте

Функция КонтекстДляПередачиНаСервер()

	Результат = Новый Структура;

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

			Результат.Вставить(Элем.Ключ, Элем.Значение);

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

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

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

&НаКлиенте

Функция КонтекстСохранямыйДляПередачиНаСервер()

	Результат = Новый Структура;

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

			Результат.Вставить(Элем.Ключ, Элем.Значение);

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

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

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

&НаКлиенте

Функция СлужебныеПеременныеДляПередачиНаСервер()

	Результат = Новый Структура;
	Результат.Вставить("КаталогПроекта", Объект.КаталогПроекта);
	Результат.Вставить("КаталогИнструментов", Объект.КаталогИнструментов);
	Результат.Вставить("КаталогФичи", КаталогТекущегоИсполняемогоФичаФайла);
	Результат.Вставить("InstrPath", Объект.КаталогИнструментов);
	Результат.Вставить("ProjectPath", Объект.КаталогПроекта);
	Результат.Вставить("FeaturePath", КаталогТекущегоИсполняемогоФичаФайла);
	Возврат Результат;

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

&НаСервере

Процедура ЯВыполняюКодВстроенногоЯзыкаНаСервереСПередачейПеременныхСервер(Стр, Контекст, КонтекстСохраняемый, СлужебныеПеременные)

	глТипСтрока = Тип("Строка");
	ТолькоСтроки = Истина;

	Context           = Контекст;
	PersistentContext = КонтекстСохраняемый;
	SavedContext      = КонтекстСохраняемый;

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

		Для Каждого Элем Из Контекст Цикл
			Если ТипЗнч(Элем.Значение) = глТипСтрока ИЛИ НЕ ТолькоСтроки Тогда
				//Для других типов это делать нельзя, т.к. шаги могут ожидать числа, строки, массивы и т.д., а тут идёт преобразование к строке.
				//Если убрать ограничение, то не будет работать передача переменных других типов, т.к. значения обернутые в $ будут сразу преобразовываться к строке
				//Т.е. перестанут работать такие шаги:
				//Тогда в переменной "$ЧисловаяПеременная$" будет находится значение типа "Число"
				Стр = СтрЗаменить(Стр, "$" + Элем.Ключ + "$", Элем.Значение);
			КонецЕсли;
		КонецЦикла;

		Для Каждого Элем Из КонтекстСохраняемый Цикл
			Если ТипЗнч(Элем.Значение) = глТипСтрока ИЛИ НЕ ТолькоСтроки Тогда
				//Для других типов это делать нельзя, т.к. шаги могут ожидать числа, строки, массивы и т.д., а тут идёт преобразование к строке.
				Стр = СтрЗаменить(Стр, "$$" + Элем.Ключ + "$$", Элем.Значение);
			КонецЕсли;
		КонецЦикла;

	КонецЕсли;

	Выполнить(Стр);

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

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

Процедура ЯВыполняюКодВстроенногоЯзыкаНаСервереБезКонтекстаСПередачейПеременныхСервер(Стр, Контекст, КонтекстСохраняемый, СлужебныеПеременные)

	глТипСтрока = Тип("Строка");
	ТолькоСтроки = Истина;

	Context           = Контекст;
	PersistentContext = КонтекстСохраняемый;
	SavedContext      = КонтекстСохраняемый;

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

		Для Каждого Элем Из Контекст Цикл
			Если ТипЗнч(Элем.Значение) = глТипСтрока ИЛИ НЕ ТолькоСтроки Тогда
				//Для других типов это делать нельзя, т.к. шаги могут ожидать числа, строки, массивы и т.д., а тут идёт преобразование к строке.
				//Если убрать ограничение, то не будет работать передача переменных других типов, т.к. значения обернутые в $ будут сразу преобразовываться к строке
				//Т.е. перестанут работать такие шаги:
				//Тогда в переменной "$ЧисловаяПеременная$" будет находится значение типа "Число"
				Стр = СтрЗаменить(Стр, "$" + Элем.Ключ + "$", Элем.Значение);
			КонецЕсли;
		КонецЦикла;

		Для Каждого Элем Из КонтекстСохраняемый Цикл
			Если ТипЗнч(Элем.Значение) = глТипСтрока ИЛИ НЕ ТолькоСтроки Тогда
				//Для других типов это делать нельзя, т.к. шаги могут ожидать числа, строки, массивы и т.д., а тут идёт преобразование к строке.
				Стр = СтрЗаменить(Стр, "$$" + Элем.Ключ + "$$", Элем.Значение);
			КонецЕсли;
		КонецЦикла;

	КонецЕсли;

	Выполнить(Стр);

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

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


Функция УбратьПарольПользователяИзСтроки(Знач Стр)

	НайденоНачалоПароля = Ложь;
	НомерСимволаНачалоПароля = 0;
	НомерСимволаКонецПароля = 0;
	Для Сч = 1 По СтрДлина(Стр) - 1 Цикл
		ТекСимвол = Сред(Стр, Сч, 1);
		СледующийСимвол = Сред(Стр, Сч + 1, 1);
		Если (ТекСимвол = "/" И СледующийСимвол = "P") ИЛИ (ТекСимвол = "/" И СледующийСимвол = "p") Тогда
			НайденоНачалоПароля = Истина;
			НомерСимволаНачалоПароля = Сч + 2;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Если НЕ НайденоНачалоПароля Тогда
		Возврат Стр;
	КонецЕсли;

	Если НомерСимволаНачалоПароля > СтрДлина(Стр) Тогда
		Возврат Стр;
	КонецЕсли;

	ПервыйСимволПароля = Сред(Стр, НомерСимволаНачалоПароля, 1);
	ПромСтр = Сред(Стр, НомерСимволаНачалоПароля + 1);
	Если ПервыйСимволПароля = """" Тогда
		Поз = Найти(ПромСтр, """");
		Если Поз > 0 Тогда
			НомерСимволаКонецПароля = Поз + НомерСимволаНачалоПароля;
		Иначе
			НомерСимволаКонецПароля = СтрДлина(ПромСтр) + НомерСимволаНачалоПароля;
		КонецЕсли;
	Иначе
		Поз = Найти(ПромСтр, " ");
		Если Поз > 0 Тогда
			НомерСимволаКонецПароля = Поз + НомерСимволаНачалоПароля - 1;
		Иначе
			НомерСимволаКонецПароля = СтрДлина(ПромСтр) + НомерСимволаНачалоПароля;
		КонецЕсли;
	КонецЕсли;

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

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

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

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

&НаКлиенте

Процедура ВыполнитьАвторизациюВСервисеСинтезаРечи1С()

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

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

	Текст = Новый ЧтениеТекста;
	Текст.Открыть(Объект.ЗаписьВидео1СПароль, "UTF-8");
	Пароль = СокрЛП(Текст.Прочитать());
	Текст.Закрыть();

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

	АвторизацияСинтезРечи1СНаСервере(Объект.ЗаписьВидео1СЛогин, Пароль);

	ВыполненаАвторизацияСервисаСинтеза1С = Истина;

	СообщитьПользователю(Локализовать("Авторизация в сервисе синтеза речи выполнена успешно"));

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

&НаКлиенте

Функция ЯзыкФичиИзТекста(Текст)
	МассивСтрок = _СтрРазделить(Текст, Символы.ПС);
	Для Сч = 0 По МассивСтрок.Количество()-1 Цикл
		Стр = НРег(МассивСтрок[Сч]);
		Поз = Найти(Стр, "#language:");
		Если Поз > 0 Тогда
			Значение = НРег(СокрЛП(Сред(Стр, Поз + 11)));
			Если ЗначениеЗаполнено(Значение) Тогда
				Возврат Значение;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;

	Возврат "";

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

&НаКлиенте

Функция ЭтоПолеДатыКлиентаТестирования(Поле)

	Попытка
		ТекстРедактирования = Поле.ПолучитьТекстРедактирования();

		Если ЭтоСтрокаПустойДаты(ТекстРедактирования) Тогда
			Возврат Истина;
		КонецЕсли;

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

	Возврат Ложь;

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

&НаКлиенте

Функция ЭтоСтрокаПустойДаты(Стр)

	Если СокрЛП(Стр) = ".  ." Тогда
		Возврат Истина;
	ИначеЕсли СокрЛП(Стр) = ".  .       :  :" Тогда
		Возврат Истина;
	ИначеЕсли Стр = "  .    " Тогда
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;

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

&НаКлиенте

Функция КешИДСценариевМассивСценариевДляВыполнения(МассивСценариевДляВыполнения)

	Результат = Новый Соответствие;
	Для Каждого Элем Из МассивСценариевДляВыполнения Цикл
		Результат.Вставить(Элем.СтрокаДерева, Элем);
	КонецЦикла;

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

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

&НаКлиенте

Функция КешШагиСценария(Шаги)

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

	Для Каждого Элем Из Шаги Цикл
		Результат.Вставить(Элем.ИдСтроки, Элем);
	КонецЦикла;

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

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

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

Функция РасширениеУстановленоСрвер(ИмяРасширения)

	Попытка
		УстановленныеРасширения = Вычислить("РасширенияКонфигурации").Получить();
	Исключение
		Возврат Ложь;
	КонецПопытки;

	Если УстановленныеРасширения = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;

	Для Каждого Расширение Из УстановленныеРасширения Цикл
		Если НРег(Расширение.Имя) = НРег(ИмяРасширения) И Расширение.Активно Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;

	Возврат Ложь;

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

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

#Область Настройки

#Область СохранениеНастроек

&НаСервере

Процедура СохранитьНастройки()

	Если Объект.РежимСамотестирования Тогда
		Возврат;
	КонецЕсли;

	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("НастройкиВыгрузки", Истина);
	Настройки = ТекущиеОбщиеНастройки(ДопПараметры);

	ХранилищеОбщихНастроек.Сохранить(ПолучитьИДСохраненияОбщихНастроек(Объект.РежимСамотестирования, Объект.ВерсияПоставки, ЭтоРежимОбученияСервер()), , Настройки);

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

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

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

#Область ВосстановлениеНастроек

&НаКлиенте


Функция ЯДелаюПодсказкуБалунУЭлементаUIAutomation(IDПоля, ТабПарам = Неопределено, ОбработчикПродолжения = Неопределено) Экспорт

	ПараметрыОтрисовки = ЗначенияПоУмолчаниюДляПодсказкиБалун();

	ДополнитьПараметрыОтрисовкиПереданныеПользователем(ПараметрыОтрисовки, ТабПарам);

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

	ДанныеПоляИзКомпоненты = Ванесса.ВнешняяКомпонентаДляСкриншотов.ЭлементПоИдентификатору(IDПоля);

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

	ДанныеПоля = Ванесса.ПрочитатьОбъектJSON(ДанныеПоляИзКомпоненты);

	МассивЭлементов = Новый Массив;
	МассивЭлементов.Добавить(ДанныеПоля);

	Left = 1000000000000000;
	Top = 1000000000000000;
	Bottom = -1;
	Right = -1;
	ОпределитьКоординатыПоМассивуЭлементовUIAutomation(МассивЭлементов, Left, Top, Bottom, Right);

	Ванесса.ПроверитьКорректностьПараметровДляВыполненияУроков(ПараметрыОтрисовки);

	Текст = ПараметрыОтрисовки.text;
	ПараметрыОтрисовки.Удалить("text");

	Ванесса.ЗапретитьВыполнениеШагов();
	ОписаниеОповещения = Новый ОписаниеОповещения("ПустоеОповещениеСПродолжениемВыполненияСценария", ЭтаФорма, ДопПараметры);
	Ванесса.ВнешняяКомпонентаДляСкриншотов.НачатьВызовПоказатьПодсказку(
		ОписаниеОповещения, Ванесса.ЗаписатьОбъектJSON(ПараметрыОтрисовки),
		Left + Цел((Right - Left)/2) + ПараметрыОтрисовки.thickness, Top + Цел((Bottom - Top)/2) + ПараметрыОтрисовки.thickness, Текст);

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

&НаКлиенте
//И я перемещаю мышку к каждой кнопке панели "$IDПанели$" Vanessa Automation
//@ЯПеремещаюМышкуККаждойКнопкеПанелиVanessaAutomation(Парам01)

Функция ЯПеремещаюМышкуККаждойКнопкеПанелиVanessaAutomation(IDРодителя) Экспорт
	ЭлементыРодителя = Ванесса.ПрочитатьОбъектJSON(Ванесса.ВнешняяКомпонентаДляСкриншотов.ПолучитьЭлементы(IDРодителя));

	Массив = Новый Массив;

	Для Каждого Элем Из ЭлементыРодителя.Tree Цикл
		Если Элем.name = "Справка" Тогда
			Продолжить;
		ИначеЕсли Элем.name = "Еще" Тогда
			Продолжить;
		КонецЕсли;

		Массив.Добавить(Элем);

	КонецЦикла;

	НадоПродолжить = Ложь;
	Для Каждого Элем Из Массив Цикл
		Если НадоПродолжить Тогда
			НадоПродолжить = Ложь;
			Продолжить;
		КонецЕсли;

		Ванесса.ВнешняяКомпонентаДляСкриншотов.ЭмуляцияДвиженияМыши(
			Элем.Size.Left + Цел((Элем.Size.Right - Элем.Size.Left)/2),
			Элем.Size.Top + Цел((Элем.Size.Bottom - Элем.Size.Top)/2), 50, 2);
		Ванесса.ВнешняяКомпонентаДляСкриншотов.sleep(250);

		НадоПродолжить = Истина;
	КонецЦикла;

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

&НаКлиенте
//И я запоминаю элемент с типом "Тип" c родителем "$IDЭлемента$" в переменную "IDЭлемента" Vanessa Automation
//@ЯЗапоминаюЭлементСТипомCРодителемВПеременнуюVanessaAutomation(Парам01,Парам02,Парам03)

Функция ЯЗапоминаюЭлементСТипомCРодителемВПеременнуюVanessaAutomation(Тип, IDРодителя, ИмяПеременной) Экспорт
	Нашли = Ложь;

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

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

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

&НаКлиенте
//И я запоминаю родителя элемента с именем "Имя" в переменную "ИмяПеременной" Vanessa Automation
//@ЯЗапоминаюРодителяЭлементаСИменемВПеременнуюVanessaAutomation(Парам01,Парам02)

Функция ЯЗапоминаюРодителяЭлементаСИменемВПеременнуюVanessaAutomation(ИмяЭлемента, ИмяПеременной) Экспорт
	PID = ПолучитьКорректныйPID("ЭтотСеанс");
	ТипЭлемента = Неопределено;
	ИмяЭлементаСТемжеРодителем = Неопределено;
	ВсеПоля = Неопределено;
	РодителиЭлементов = Новый Соответствие;
	Элемент = ОпределитьЭлементUIAutomationЭлементаФормыVAПоЕгоИмени(PID, ИмяЭлемента, ТипЭлемента, ВсеПоля, ИмяЭлементаСТемжеРодителем, РодителиЭлементов);
	РодительЭлемента = Ванесса.ПрочитатьОбъектJSON(Ванесса.ВнешняяКомпонентаДляСкриншотов.ПолучитьРодителяЭлемента(Элемент.Id));
	Ванесса.СохранитьЗначениеПеременнойВКонтекст(ИмяПеременной, РодительЭлемента.Id);
КонецФункции

&НаКлиенте
//И я запоминаю родителя родителя элемента с именем "ИмяЭлемента" в переменную "IDРодителя" Vanessa Automation
//@ЯЗапоминаюРодителяРодителяЭлементаСИменемВПеременнуюVanessaAutomation(Парам01,Парам02)

Функция ЯЗапоминаюРодителяРодителяЭлементаСИменемВПеременнуюVanessaAutomation(ИмяЭлемента,ИмяПеременной) Экспорт
	PID = ПолучитьКорректныйPID("ЭтотСеанс");
	ТипЭлемента = Неопределено;
	ИмяЭлементаСТемжеРодителем = Неопределено;
	ВсеПоля = Неопределено;
	РодителиЭлементов = Новый Соответствие;
	Элемент = ОпределитьЭлементUIAutomationЭлементаФормыVAПоЕгоИмени(PID, ИмяЭлемента, ТипЭлемента, ВсеПоля, ИмяЭлементаСТемжеРодителем, РодителиЭлементов);
	РодительЭлемента = Ванесса.ПрочитатьОбъектJSON(Ванесса.ВнешняяКомпонентаДляСкриншотов.ПолучитьРодителяЭлемента(Элемент.Id));
	РодительЭлемента = Ванесса.ПрочитатьОбъектJSON(Ванесса.ВнешняяКомпонентаДляСкриншотов.ПолучитьРодителяЭлемента(РодительЭлемента.Id));
	Ванесса.СохранитьЗначениеПеременнойВКонтекст(ИмяПеременной, РодительЭлемента.Id);
КонецФункции

&НаКлиенте
//И я запоминаю элемент с именем "Имя" в переменную "ИмяПеременной" Vanessa Automation
//@ЯЗапоминаюЭлементСИменемВПеременнуюVanessaAutomation(Парам01,Парам02)

Функция ЯЗапоминаюЭлементСИменемВПеременнуюVanessaAutomation(ИмяЭлемента, ИмяПеременной) Экспорт
	PID = ПолучитьКорректныйPID("ЭтотСеанс");
	ТипЭлемента = Неопределено;
	ИмяЭлементаСТемжеРодителем = Неопределено;
	ВсеПоля = Неопределено;
	РодителиЭлементов = Новый Соответствие;
	Элемент = ОпределитьЭлементUIAutomationЭлементаФормыVAПоЕгоИмени(PID, ИмяЭлемента, ТипЭлемента, ВсеПоля, ИмяЭлементаСТемжеРодителем, РодителиЭлементов);
	Ванесса.СохранитьЗначениеПеременнойВКонтекст(ИмяПеременной, Элемент.Id);
КонецФункции

&НаКлиенте
//И я запоминаю элемент UI Automation в переменную
//@ЯЗапоминаюЭлементUIAutomationВПеременную(ТабПарам)


Функция ВТЧПолеДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ТЧ = Ванесса.НайтиТЧПоИмени(ИмяТЧ);

	Если ИскатьПоИмени Тогда
		ПолеРеквизит = Ванесса.НайтиРеквизитТаблицы(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени,ТЧ);
	Иначе
		ПолеРеквизит = Ванесса.НайтиРеквизитТаблицы(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени,ТЧ);
	КонецЕсли;

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

	Нашли = ПолеРеквизит.ТекущееТолькоПросмотр();

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

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

&НаКлиенте
//И В таблице "ИмяТЧ" поле "ИмяРеквизита" доступно только для просмотра
//@ВТаблицеПолеДоступноТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТаблицеПолеДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени);
КонецФункции

&НаКлиенте
//И В таблице "ИмяТЧ" поле с именем "ИмяРеквизита" доступно только для просмотра
//@ВТЧПолеСИменемДоступноТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТЧПолеСИменемДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита, Истина);
КонецФункции

&НаКлиенте
//И В таблице "ИмяТЧ" поле с именем "ИмяРеквизита" доступно только для просмотра
//@ВТаблицеПолеСИменемДоступноТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТаблицеПолеСИменемДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита, Истина);
КонецФункции

&НаКлиенте
//И В таблице "ИмяТЧ" поле "ИмяРеквизита" доступно не только для просмотра
//@ВТЧПолеДоступноНеТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТЧПолеДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ТЧ = Ванесса.НайтиТЧПоИмени(ИмяТЧ);

	Если ИскатьПоИмени Тогда
		ПолеРеквизит = Ванесса.НайтиРеквизитТаблицы(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени,ТЧ);
	Иначе
		ПолеРеквизит = Ванесса.НайтиРеквизитТаблицы(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени,ТЧ);
	КонецЕсли;

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

	Нашли = ПолеРеквизит.ТекущееТолькоПросмотр();

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

	КонецЕсли;

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

&НаКлиенте
//И В таблице "ИмяТЧ" поле "ИмяРеквизита" доступно не только для просмотра
//@ВТаблицеПолеДоступноНеТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТаблицеПолеДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени);
КонецФункции

&НаКлиенте
//И В таблице "ИмяТЧ" поле с именем "ИмяРеквизита" доступно не только для просмотра
//@ВТЧПолеСИменемДоступноНеТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТЧПолеСИменемДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита, Истина);
КонецФункции

&НаКлиенте
//И В таблице "ИмяТЧ" поле с именем "ИмяРеквизита" доступно не только для просмотра
//@ВТаблицеПолеСИменемДоступноНеТолькоДляПросмотра(ИмяТЧ, ИмяРеквизита)

Функция ВТаблицеПолеСИменемДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита,ИскатьПоИмени = Ложь) Экспорт
	ВТЧПолеДоступноНеТолькоДляПросмотра(ИмяТЧ,ИмяРеквизита, Истина);
КонецФункции

// } доступность

&НаКлиенте
//Тогда в таблице с именем "ТабличнаяЧасть1" я выделяю все строки
//@ВТаблицеСИменемЯВыделяюВсеСтроки(Парам01)

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

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

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

&НаКлиенте
//Тогда в таблице "ТабличнаяЧасть1" я выделяю все строки
//@ВТаблицеЯВыделяюВсеСтроки(Парам01)

Функция ВТаблицеЯВыделяюВсеСтроки(ИмяТЧ) Экспорт
	ВТаблицеСИменемЯВыделяюВсеСтроки(ИмяТЧ);
КонецФункции

&НаКлиенте
//И в таблице "ИмяТаблицы" я выделяю все строки выше текущей
//@ВТаблицеЯВыделяюВсеСтрокиВышеТекущей(Парам01)

Функция ВТаблицеЯВыделяюВсеСтрокиВышеТекущей(ИмяТЧ) Экспорт
	ТЧ = Ванесса.НайтиТЧПоИмени(ИмяТЧ);

	Попытка
		ТЧ.ПерейтиКПредыдущейСтроке();
	Исключение
	КонецПопытки;

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

&НаКлиенте
//И в таблице "ИмяТаблицы" я выделяю все строки ниже текущей
//@ВТаблицеЯВыделяюВсеСтрокиНижеТекущей(Парам01)

Функция ВТаблицеЯВыделяюВсеСтрокиНижеТекущей(ИмяТЧ) Экспорт
	ТЧ = Ванесса.НайтиТЧПоИмени(ИмяТЧ);

	Попытка
		ТЧ.ПерейтиКСледующейСтроке();
	Исключение
	КонецПопытки;

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

&НаКлиенте
//И в поле "&Что искать" ввожу значение переменной "Документ2_Сценарий_1"
//@ВПолеВвожуЗначениеПеременной(Парам01,Парам02)

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

&НаКлиенте
//И в поле "&Что искать" я ввожу значение переменной "Документ2_Сценарий_1"
//@ВПолеЯВвожуЗначениеПеременной(Парам01,Парам02)

Функция ВПолеЯВвожуЗначениеПеременной(ИмяПоля,ИмяПеременной,ИскатьПоИмени = Ложь) Экспорт
	ВПолеВвожуЗначениеПеременной(ИмяПоля,ИмяПеременной,ИскатьПоИмени);
КонецФункции

&НаКлиенте
//И в Таблицу "ТабличнаяЧасть1" поле "Номер" ввожу значение переменной "НомерДок"
//@ВТаблицуВПолеВвожуЗначениеПеременной(Парам01,Парам02,Парам03)


Функция ТабличныйДокументФормыСИменемСталРавенМакетуСИменем(ИмяРеквизита, ИмяМакета, СравнениеПоШаблону = Ложь) Экспорт

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

	ИмяФайлаМакета = Неопределено;
	ТабДокБыло = Ванесса.ПолучитьЭталонМакета(ИмяМакета, ИмяФайлаМакета);

	ТекстОшибки = "";
	ПодробныйТекстОшибки = Неопределено;

	НадоВызватьИсключение = Истина;
	КоличествоПопыток = 1;

	Для СчетчикПопыток = 1 По КоличествоПопыток Цикл
		Попытка

			ДопПараметрыПоиска = Новый Структура;
			//ДопПараметрыПоиска.Вставить("КоличествоПопыток", 1);
			ЭлементТД   = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку(ИмяРеквизита, Истина, Истина, Тип("ТестируемоеПолеФормы"), ДопПараметрыПоиска);
			ТабДокСтало = Ванесса.ПолучитьТабличныйДокументTestClient(ЭлементТД);

			Если ТабДокСтало = Неопределено И Ванесса.Версия8325ИлиВыше Тогда
				Ванесса.sleep(5);
				ТекстСообщения = Ванесса.Локализовать("Попытка ещё раз получить табличный документ, т.к. было получено Неопределено");
				Ванесса.ЗаписатьЛогВЖРИнформация("ТабличныйДокументФормыСИменемСталРавенМакетуСИменем", ТекстСообщения);
				ТабДокСтало = Ванесса.ПолучитьТабличныйДокументTestClient(ЭлементТД);
			КонецЕсли;

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

			МакетыСовпали = Ложь;
			ТекстИсключения = "";
			Попытка
				Ванесса.ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениям(ТабДокБыло, ТабДокСтало,,,, ДопПараметры);
				МакетыСовпали = Истина;
			Исключение
				ТекстИсключения = ОписаниеОшибки();
			КонецПопытки;

			Если НЕ МакетыСовпали Тогда
				ТабДокБыло1 = Ванесса.УбратьОтступыИзМакета(ТабДокБыло);
				ТабДокСтало1 = Ванесса.УбратьОтступыИзМакета(ТабДокСтало);

				Попытка
					Ванесса.ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениям(ТабДокБыло1, ТабДокСтало1,,,, ДопПараметры);
				Исключение
					ТекстИсключения = ТекстИсключения;

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

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

			НадоВызватьИсключение = Ложь;
			Прервать;

		Исключение
			ПодробныйТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
			ТекстОшибки = ОписаниеОшибки();
			Если СчетчикПопыток < КоличествоПопыток Тогда
				Ванесса.sleep(1);
			КонецЕсли;
			Ванесса.ОбработатьСменуАктивногоОкна();
		КонецПопытки;

	КонецЦикла;

	Если НадоВызватьИсключение Тогда

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

		Если ЗначениеЗаполнено(ПодробныйТекстОшибки) Тогда
			//Чтобы получить полный стек вызова надо записать в ЖР ПодробныйТекстОшибки
			Ванесса.ЗаписатьЛогВЖРОшибка("ТабличныйДокументФормыСИменемСталРавенМакетуСИменем", ПодробныйТекстОшибки);
		КонецЕсли;

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

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

&НаКлиенте
//Дано Табличный документ "РеквизитТабличныйДокумент" стал равен "ИмяМакета"
//@ТабличныйДокументСталРавенМакету(Парам01,Парам02)

Функция ТабличныйДокументСталРавенМакету(ИмяРеквизита, ИмяМакета) Экспорт
	ТабличныйДокументФормыСИменемСталРавенМакетуСИменем(ИмяРеквизита, ИмяМакета);
КонецФункции

&НаКлиенте
//Дано Табличный документ "РеквизитТабличныйДокумент" равен "ИмяМакета"
//@ТабличныйДокументРавенМакету(Парам01,Парам02)

Функция ТабличныйДокументРавенМакету(ИмяРеквизита, ИмяМакета) Экспорт
	ТабличныйДокументФормыСИменемСталРавенМакетуСИменем(ИмяРеквизита, ИмяМакета);
КонецФункции

&НаКлиенте
//Дано Табличный документ "РеквизитТабличныйДокумент" равен макету "ИмяМакета" по шаблону
//@ТабличныйДокументРавенМакетуПоШаблону(Парам01,Парам02)

Функция ТабличныйДокументРавенМакетуПоШаблону(ИмяРеквизита, ИмяМакета) Экспорт
	ТабличныйДокументФормыСИменемСталРавенМакетуСИменем(ИмяРеквизита, ИмяМакета, Истина);
КонецФункции

&НаКлиенте
//Дано В последнем сообщении TestClient есть строка "Стр"
//@ВПоследнемСообщенииTestClientЕстьСтрока(Стр)

Функция ВПоследнемСообщенииTestClientЕстьСтрока(Знач Стр) Экспорт
	//Стр = Ванесса.ПолучитьЗначениеИзКонтекстаЕслиЭтоВозможно(Стр);
	МассивСообщений = Ванесса.ПолучитьАктивноеОкноИзТестовоеПриложение().ПолучитьТекстыСообщенийПользователю();
	Если МассивСообщений.Количество() = 0 Тогда
		ВызватьИсключение Ванесса.ПолучитьТекстСообщенияПользователю("Не найдено ни одного сообщения пользователю.");
	КонецЕсли;
	Если Найти( НРег( МассивСообщений[ МассивСообщений.Количество() - 1 ]), НРег( Стр )) = 0
		И Найти( НРег( МассивСообщений[ МассивСообщений.Количество() - 1 ]), НРег(СтрЗаменить(Стр, "\n", Символы.ПС))) = 0
		Тогда
		ТекстСообщения = Ванесса.ПолучитьТекстСообщенияПользователю("Строка <%1> не найдена в последнем сообщении пользователю. Найдено: %2");
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",Стр);
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%2",МассивСообщений[ МассивСообщений.Количество()- 1]);
		ВызватьИсключение ТекстСообщения;
	КонецЕсли;
КонецФункции

&НаКлиенте
//Дано В активном окне открылась форма с заголовком "Заголовок формы"
//@ВАктивномОкнеОткрыласьФормаСЗаголовком(Парам01)

Функция ВАктивномОкнеОткрыласьФормаСЗаголовком(Парам01) Экспорт
	АктивноеОкно = ПолучитьАктивноеОкноИзТестовоеПриложение();

	Ванесса.ОбработатьСменуАктивногоОкна();

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

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

Функция ПолучитьАктивныеФоновыеЗадания(СтруктураОтбора = Неопределено)
	Если СтруктураОтбора = Неопределено Тогда
		СтруктураОтбора = Новый Структура();
	КонецЕсли;

	СтруктураОтбора.Вставить("Состояние",			СостояниеФоновогоЗадания.Активно);
	СтруктураОтбора.Вставить("РегламентноеЗадание",	Неопределено);

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

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

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

	Возврат КонтролируемыеФоновыеЗадания;
КонецФункции

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


Функция ЯЗапоминаюЭлементФормыКлиентаТестированияВПеременнуюUIAutomationРасширение(ИмяЭлемента, ИмяПеременной, ИскатьПоИмени = Ложь) Экспорт

	ОбработчикИмяПеременной = ИмяПеременной;

	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("КоличествоПопыток", 1);
	ПолеРеквизит = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку(ИмяЭлемента, ИскатьПоИмени, Истина,,ДопПараметры);

	ОбработчикИмяЭлемента = ПолеРеквизит.Имя;

	АктивноеОкно = Ванесса.ПолучитьАктивноеОкноИзТестовоеПриложение();
	ЗаголовокАктивногоОкна = АктивноеОкно.Заголовок;

	Ванесса.ОткрытьНавигационнуюСсылку("e1cib/app/Обработка.VAExtension_ДанныеТекущегоОкна");

	РеквизитВыражениеВычислено = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку("ВыражениеВычислено", Истина);
	РеквизитЗначениеРезультат = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку("ЗначениеРезультат", Истина);
	РеквизитЗначениеВыражение = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку("ЗначениеВыражение", Истина);
	РеквизитЗначениеЗаголовокОкна = Ванесса.НайтиРеквизитОткрытойФормыПоЗаголовку("ЗначениеЗаголовокОкна", Истина);
	РеквизитЗначениеЗаголовокОкна.ВвестиТекст(ЗаголовокАктивногоОкна);

	//Получаем значение текущей подсказки
	ПараметрВыражение = "_ТекущееОкно.Элементы.%1.Подсказка";
	СтрокаUID = Строка(Новый УникальныйИдентификатор);
	ПараметрВыражение = Ванесса.ПодставитьПараметрыВСтроку(ПараметрВыражение, ОбработчикИмяЭлемента, СтрокаUID);
	РеквизитЗначениеВыражение.ВвестиТекст(ПараметрВыражение);

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

	КнопкаВычислитьВыражение.Нажать();

	ОбработчикТекущаяПодсказка = Неопределено;

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

		ОбработчикТекущаяПодсказка = Ванесса.ПолучитьПредставлениеДанныхЭлементаФормы(РеквизитЗначениеРезультат);

	Исключение
		Ванесса.ЗаписатьЛогВЖРИнформация("ЯВыполняюВыражениеВТекущемОкнеРасширение", ОписаниеОшибки());
	КонецПопытки;

	//Меняем текст подсказки
	РеквизитВыражениеВычислено.УстановитьОтметку();
	ПараметрВыражение = "_ТекущееОкно.Элементы.%1.Подсказка = ""%2""";
	ОбработчикНовыйТекстПодсказка = Строка(Новый УникальныйИдентификатор);
	ПараметрВыражение = Ванесса.ПодставитьПараметрыВСтроку(ПараметрВыражение, ОбработчикИмяЭлемента, ОбработчикНовыйТекстПодсказка);
	РеквизитЗначениеВыражение.ВвестиТекст(ПараметрВыражение);

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

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

		ПредставлениеДанных = Ванесса.ПолучитьПредставлениеДанныхЭлементаФормы(РеквизитЗначениеРезультат);

		КнопкаЗакрытьФорму = АктивноеОкно.НайтиОбъект(Тип("ТестируемаяКнопкаФормы"),,"ЗакрытьФорму");
		Попытка
			КнопкаЗакрытьФорму.Нажать();
		Исключение
			Ванесса.ЗаписатьЛогВЖРИнформация("ВычислениеВыражения", ОписаниеОшибки());
		КонецПопытки;
	Исключение
		Ванесса.ЗаписатьЛогВЖРИнформация("ЯВыполняюВыражениеВТекущемОкнеРасширение", ОписаниеОшибки());
	КонецПопытки;

	Ванесса.ЗапретитьВыполнениеШагов();
	ПодключитьОбработчикОжидания("ЯЗапоминаюЭлементФормыКлиентаТестированияВПеременнуюUIAutomationрасширениеПродолжение", 0.1, Истина);

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

&НаКлиенте
//И я запоминаю элемент формы клиента тестирования с именем "ИмяЭлемента" в переменную "ИмяПеременной" UI Automation (расширение)
//@ЯЗапоминаюЭлементФормыКлиентаТестированияСИменемВПеременнуюUIAutomationРасширение(Парам01,Парам02)

Функция ЯЗапоминаюЭлементФормыКлиентаТестированияСИменемВПеременнуюUIAutomationРасширение(ИмяЭлемента, ИмяПеременной) Экспорт
	ЯЗапоминаюЭлементФормыКлиентаТестированияВПеременнуюUIAutomationРасширение(ИмяЭлемента, ИмяПеременной, Истина);
КонецФункции

&НаКлиенте
// И я эмулирую сканирование штрихкода БПО ""4670003110011"" через буфер обмена
// @ЯЭмулируюСканированиеШтрихкодаБПОЧерезБуферОбмена(Парам01)

Функция ЯЭмулируюСканированиеШтрихкодаБПОЧерезБуферОбмена(Знач Штрихкод) Экспорт

	ГлавноеОкноТестируемого = Ванесса.ПолучитьГлавноеОкноИзТестовоеПриложение();

	КомандаЭмуляцияШтрихкода = "e1cib/command/ОбщаяКоманда.VAExtension_ЭмуляцияШтрихкода";

	Штрихкод = СтрЗаменить(Штрихкод,"\\x_GS",Символ(29));
	Штрихкод = СтрЗаменить(Штрихкод,"\x_GS",Символ(29));

	БуферОбменаVA = Ванесса.БуферОбменаVA();

	ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПоместитьВБуферОбменаVA", ЭтаФорма, КомандаЭмуляцияШтрихкода);

	БуферОбменаVA.НачатьВызовЗаписатьТекст(ОписаниеОповещения, Штрихкод);

	Ванесса.ЗапретитьВыполнениеШагов();

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

&НаКлиенте
// И я эмулирую сканирование штрихкода БПО ""4670003110011"" через файл события (Расширение)
// @ЯЭмулируюСканированиеШтрихкодаБПОЧерезФайлСобытияРасширение(Парам01)

Функция ЯЭмулируюСканированиеШтрихкодаБПОЧерезФайлСобытияРасширение(Знач Штрихкод) Экспорт

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

	_СписокPIDКлиентовСМониторингомСобытий = КонтекстСохраняемый._СписокPIDКлиентовСМониторингомСобытий;
	ТекущийPIDКлиента = Ванесса.ТекущиеДанныеКлиентаТестирования().PIDКлиентаТестирования;
	Каталог = _СписокPIDКлиентовСМониторингомСобытий.Получить(ТекущийPIDКлиента);

	Если Каталог <> Неопределено Тогда

		Штрихкод = СтрЗаменить(Штрихкод,"\\x_GS",Символ(29));
		Штрихкод = СтрЗаменить(Штрихкод,"\x_GS",Символ(29));

		ТекстСобытия = Новый Структура;
		ТекстСобытия.Вставить("ВидСобытия","СканерШтрихкода");
		ТекстСобытия.Вставить("Данные",Штрихкод);

		УникальныйИдентификаторСобытия = Новый УникальныйИдентификатор;
		ФайлСобытия = Каталог + ПолучитьРазделительПути() + "Event_BK_"+Строка(УникальныйИдентификаторСобытия)+".json";

		ЗаписьJson = Новый ЗаписьJson();
		ЗаписьJson.ОткрытьФайл(ФайлСобытия);
		ЗаписатьJSON(ЗаписьJson, ТекстСобытия);
		ЗаписьJson.Закрыть();

		КонтекстСохраняемый.Вставить("_ИмяФайлаПоследнегоСобытия", ФайлСобытия);
	Иначе
		ВызватьИсключение "В текущем клиенте не запущена система внешних событий";
	КонецЕсли;

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

&НаКлиенте
// И я генерирую код маркировки честного знака для GTIN "GTIN" типа "ТипКМ" в переменную "ИмяПеременной" (расширение)
// @ЯГенерируюКодМаркировкиЧестногоЗнакаДляGTINТипаВПеременнуюРасширение(Парам01,Парам02,Парам03)


Функция ДляКаждойСтрокиТаблицыЯВыполняюИспользуяКолонку(ИмяТЧ,ИмяКолонки) Экспорт
	ДляКаждойСтрокиТаблицыЯВыполняю(ИмяТЧ,ИмяКолонки);
КонецФункции

&НаКлиенте
//Пока в таблице "ТабличнаяЧасть1" количество строк ">" 0 Тогда
//@ПокаВТаблицеКоличествоСтрокТогда(Парам01,Парам02,Парам03)

Функция ПокаВТаблицеКоличествоСтрокТогда(ИмяТаблицы,Знач Сравнение,КоличествоСтрок) Экспорт
	ИмяЦикла = "_Цикл_" + Формат(Ванесса.ПолучитьСостояниеVanessaAutomation().ТекущийШаг.ИдСтроки, "ЧГ=; ЧН=0");

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

			Возврат Неопределено;
		КонецЕсли;
	КонецЕсли;

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

	Контекст.Вставить("_ВременнаяТаблицаВычислитьВыражение",Таблица);
	Сравнение = Ванесса.ПолучитьОператорПоТексту(Сравнение);
	Выражение = "Контекст._ВременнаяТаблицаВычислитьВыражение.Количество() " + Сравнение +  " " + Формат(КоличествоСтрок, "ЧГ=; ЧН=0");

	Попытка
		Результат = Ванесса.ВычислитьВнутреннееВыражение(Выражение);
	Исключение
		Результат = Выражение;
	КонецПопытки;

	Если Результат Тогда
		Ванесса.УстановитьРезультатУсловия(Истина);
	Иначе
		Ванесса.УстановитьРезультатУсловия(Ложь);
	КонецЕсли;

	Контекст.Удалить("_ВременнаяТаблицаВычислитьВыражение");
КонецФункции

&НаКлиенте
//Если служебное условие, в котором меняется служебная переменная истинно тогда
//@СлужебноеУсловиеВКоторомМеняетсяСлужебнаяПеременнаяИстинноТогда()

Функция СлужебноеУсловиеВКоторомМеняетсяСлужебнаяПеременнаяИстинноТогда() Экспорт
	Контекст.СлужебнаяПеременная1 = Контекст.СлужебнаяПеременная1 + 1;
	Если Контекст.СлужебнаяПеременная1 < 4 Тогда
		Ванесса.УстановитьРезультатУсловия(Истина);
		Возврат Неопределено;
	КонецЕсли;

	Ванесса.УстановитьРезультатУсловия(Ложь);
КонецФункции

&НаКлиенте

Функция ОбработчикОжиданияВТечениеСекундЯВыполняю()
	ИмяОбработчика = "ОбработчикОжиданияВТечениеСекундЯВыполняю";

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

	Ванесса.ПроверитьНеобходимостьЗакрытьСистемныйДиалог();

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

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

					Если ЗначениеТЧ <> Неопределено Тогда
						МакетЗначениеТЧ = Ванесса.ПреобразоватьЗначениеВМакет(ЗначениеТЧ);
						Ванесса.ПрикрепитьМакетКСценарию(МакетЗначениеТЧ,Ванесса.Локализовать("ТекущееЗначениеТаблицы"));
					КонецЕсли;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

		Если Контекст.Свойство(ИмяЦикла) Тогда
			Контекст.Удалить(ИмяЦикла);
			Контекст.Удалить(ИмяЦикла + "_ДатаОкончанияОбработкиОжидания");
		КонецЕсли;

		Ванесса.ПродолжитьВыполнениеШагов(Истина,Ванесса.ПолучитьТекстСообщенияПользователю(ТекстСообщения));

		Возврат Неопределено;
	КонецЕсли;

	Ванесса.УстановитьРезультатУсловия(Истина);
	Ванесса.ПродолжитьВыполнениеШагов();
КонецФункции

&НаКлиенте
//И в течение 10 секунд я выполняю
//@ВТечениеСекундЯВыполняю(Парам01)

Функция ВТечениеСекундЯВыполняю(КоличествоСекунд) Экспорт
	СостояниеVA = Ванесса.ПолучитьСостояниеVanessaAutomation();
	ИдСтроки                 = СостояниеVA.ТекущийШаг.ИдСтроки;
	ИмяЦикла                 = "_Цикл_" + Формат(ИдСтроки, "ЧГ=; ЧН=0");

	Если Контекст.Свойство("ЗавершитьВыполнениеЦикла") Тогда
		Если Контекст.ЗавершитьВыполнениеЦикла = Истина Тогда
			Контекст.ЗавершитьВыполнениеЦикла = Ложь;
			Ванесса.УстановитьРезультатУсловия(Ложь);
			Если Контекст.Свойство(ИмяЦикла) Тогда
				Контекст.Удалить(ИмяЦикла);
			КонецЕсли;
			Если Контекст.Свойство(ИмяЦикла + "_ДатаОкончанияОбработкиОжидания") Тогда
				Контекст.Удалить(ИмяЦикла + "_ДатаОкончанияОбработкиОжидания");
			КонецЕсли;

			Возврат Неопределено;
		КонецЕсли;
	КонецЕсли;

	Ванесса.ЗапретитьВыполнениеШагов();

	Если Не Контекст.Свойство(ИмяЦикла) Тогда
		//при запуске первой итерации определяем параметры окончания
		Контекст.Вставить(ИмяЦикла, Истина);

		ДатаНачалаОбработкиОжидания       = ТекущаяДата();
		КоличествоСекундОбработкаОжидания = Ванесса.ЗначениеТаймаутаДляАсинхронногоШага(КоличествоСекунд);
		ДатаОкончанияОбработкиОжидания    = ДатаНачалаОбработкиОжидания + КоличествоСекундОбработкаОжидания;

		Контекст.Вставить(ИмяЦикла + "_ДатаОкончанияОбработкиОжидания", ДатаОкончанияОбработкиОжидания);
	КонецЕсли;

	ДатаОкончанияОбработкиОжидания = Контекст[ИмяЦикла + "_ДатаОкончанияОбработкиОжидания"];

	ПодключитьОбработчикОжидания("ОбработчикОжиданияВТечениеСекундЯВыполняю", 1, Истина);
КонецФункции

&НаКлиенте
//Тогда я прерываю цикл
//@ЯПрерываюЦикл()

Функция ЯПрерываюЦикл() Экспорт
	Контекст.Вставить("ЗавершитьВыполнениеЦикла",Истина);
	Ванесса.УстановитьПризнакЧтоСледующимШагомДолженБытьШагЦикла();
КонецФункции

&НаКлиенте
//Тогда я продолжаю цикл
//@ЯПродолжаюЦикл()

Функция ЯПродолжаюЦикл() Экспорт
	Ванесса.УстановитьПризнакЧтоСледующимШагомДолженБытьШагЦикла();
КонецФункции

&НаКлиенте
//И я делаю 10 раз
//@ЯДелаюРаз(Парам01)


Функция СоздатьОбъект_Документ_или_БизнесПроцесс_или_Задача(МенеджерВсехВидов, ПротоДанные, ПротоОбъект)
	ЭтоДокумент = МенеджерВсехВидов = Документы;
	ЭтоБизнесПроцесс = МенеджерВсехВидов = БизнесПроцессы;
	ЭтоЗадача = МенеджерВсехВидов = Задачи;

	Если ЭтоДокумент Тогда
		ПредставлениеМенеджера = "Документы";
	ИначеЕсли ЭтоБизнесПроцесс Тогда
		ПредставлениеМенеджера = "БизнесПроцессы";
	ИначеЕсли ЭтоЗадача Тогда
		ПредставлениеМенеджера = "Задачи";
	Иначе
		ТекстСообщения = ПолучитьТекстСообщенияПользователю("Требуется документ, бизнес-процесс или задача. Неизвестный менеджер %1.%2 . Переменная %3");
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",ПротоОбъект.Тип);
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%2",ПротоОбъект.Вид);
		ТекстСообщения = СтрЗаменить(ТекстСообщения,"%3",ПротоОбъект.ИмяПеременной);
		ВызватьИсключение ТекстСообщения;
	КонецЕсли;

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

	Если ПротоОбъект.Режимы.ТолькоСоздание И Объект<>Неопределено Тогда
		Возврат ПротоОбъект.Объект;
	КонецЕсли;

	//Создание объекта
	Если Объект = Неопределено Тогда
		Попытка
			Если ЭтоДокумент Тогда
				Объект = МенеджерОбъекта.СоздатьДокумент();
			ИначеЕсли ЭтоБизнесПроцесс Тогда
				Объект = МенеджерОбъекта.СоздатьБизнесПроцесс();
			ИначеЕсли ЭтоЗадача Тогда
				Объект = МенеджерОбъекта.СоздатьЗадачу();
			КонецЕсли;
		Исключение
			Ошибка = ОписаниеОшибки();
			ТекстСообщения = ПолучитьТекстСообщенияПользователю("%1.%2 не удалось создать новый элемент.%3");
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%1",ПредставлениеМенеджера);
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%2",ПротоОбъект.Вид);
			ТекстСообщения = СтрЗаменить(ТекстСообщения,"%3",Символы.ПС+Ошибка);
			ВызватьИсключение ТекстСообщения;
		КонецПопытки;

		//Установка ссылки
		Если Объект.ЭтоНовый() Тогда
			Если НЕ ЗначениеЗаполнено(ПротоОбъект.Объект) Тогда
				ПротоОбъект.Объект = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор);
			КонецЕсли;
			Объект.УстановитьСсылкуНового(ПротоОбъект.Объект);
		КонецЕсли;
	КонецЕсли;

	//Заполняем реквизиты
	НаборМдРеквизитов = НаборРеквизитовМетаданных(ПротоОбъект.Тип, Объект.Метаданные());
	Для каждого стрПоле Из ПротоОбъект.ПоляОбъекта Цикл
		Объект[стрПоле.Имя] = ПолучитьЗначениеПоля(ПротоДанные,стрПоле,НаборМдРеквизитов);
	КонецЦикла;

	Для каждого мдТабЧасть из Объект.Метаданные().ТабличныеЧасти Цикл
		Объект[мдТабЧасть.Имя].Очистить();
	КонецЦикла;
	Для каждого ТабЧасть из ПротоОбъект.ТабличныеЧасти Цикл
		Для каждого СтрокаТабЧасти Из ТабЧасть.Значение Цикл
			СтрокаТабЧастиОбъекта = Объект[ТабЧасть.Ключ].Добавить();
			объектМетаданныеТабличнаяЧасть = Объект.Метаданные().ТабличныеЧасти[ТабЧасть.Ключ];
			НаборМдРеквизитовТЧ = объектМетаданныеТабличнаяЧасть.Реквизиты;
			Для каждого стрПоле Из СтрокаТабЧасти Цикл
				СтрокаТабЧастиОбъекта[стрПоле.Имя] = ПолучитьЗначениеПоля(ПротоДанные,стрПоле,НаборМдРеквизитовТЧ);
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;

	//Служебные поля и значения
	Если НЕ ЗначениеЗаполнено(Объект.Дата) Тогда
		Объект.Дата = ТекущаяДата();
	КонецЕсли;
	Если НЕ ЗначениеЗаполнено(Объект.Номер) тогда
		Объект.УстановитьНовыйНомер();
	КонецЕсли;

	ЗаполнитьОбменДанными(Объект, ПротоДанные, ПротоОбъект);
	ЗаполнитьДополнительныеСвойства(Объект, ПротоДанные, ПротоОбъект);

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

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


Процедура КомпоновщикОтборПослеУдаления(Элемент)

	ОбновитьНастройкиПостроителяВТаблицеДляВыгрузки();

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

&НаКлиенте

Процедура ОбновитьНастройкиПостроителяВТаблицеДляВыгрузки()

	ТекущаяСтрока = Элементы.ДеревоМетаданных.ТекущиеДанные;
	Если Объект.КомпоновщикНастроекКомпоновкиДанных.Настройки.Отбор.Элементы.Количество() > 0 Тогда

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

	Иначе

		ТекущаяСтрока.НастройкиКомпоновщика = Неопределено;
		ТекущаяСтрока.ИспользоватьОтбор    = ЛОЖЬ;

	КонецЕсли;

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

&НаКлиенте

Процедура ПоказатьРезультатОтбора(Команда)

	// показать выбранные записи
	Если Элементы.КомпоновщикОтбор.Доступность <> Истина
		ИЛИ Элементы.ДеревоМетаданных.ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;

	ТабличныйДокумент = ПолучитьРезультатОтбораНаСервере();
	ТабличныйДокумент.Показать(НСтр("ru='Выбранные объекты';en='Selected objects'"));

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

&НаСервере

Функция ПолучитьРезультатОтбораНаСервере()

	СтрокаДерева = Объект.ДеревоМетаданных.НайтиПоИдентификатору(Элементы.ДеревоМетаданных.ТекущаяСтрока);
	ТабличныйДокумент = Объект().СформироватьОтчетПоОтобраннымДанным(СтрокаДерева);

	Возврат ТабличныйДокумент;

КонецФункции // ПолучитьРезультатОтбораНаСервере()

&НаКлиенте

Процедура ДополнительныеСвойства(Команда)
	Элементы.ФормаДополнительныеСвойства.Пометка = НЕ Элементы.ФормаДополнительныеСвойства.Пометка;
	Элементы.ДополнительныеСвойства.Видимость = Элементы.ФормаДополнительныеСвойства.Пометка;
КонецПроцедуры

&НаКлиенте

Процедура УровеньВыгрузкиПриИзменении(Элемент)
	Если Объект.УровеньВыгрузки = 0 Тогда
		СтрокаКонфигурации = Объект.ДеревоМетаданных.ПолучитьЭлементы()[0];
		СтрокаКонфигурации.ВыгружатьПриНеобходимости = 1;
		ДеревоМетаданныхВыгружатьПриНеобходимостиПриИзменении(Элемент);
	Иначе
		ПересчитатьВыгружаемыеПоСсылке(Элемент);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ПередЗакрытием(Отказ, ЗавершениеРаботыСтандартнаяОбработка, ТекстПредупреждения, СтандартнаяОбработка)

	ЭтоЗавершениеРаботы = СтандартнаяОбработка <> Неопределено
								И ЗавершениеРаботыСтандартнаяОбработка = Истина;

	Если Не ЭтоЗавершениеРаботы Тогда

		Отказ = (Вопрос("Вы действительно хотите закрыть обработку?", РежимДиалогаВопрос.ДаНет,,,"Подтвердите выход") = КодВозвратаДиалога.Нет);

	КонецЕсли;
КонецПроцедуры