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

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

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

	СтруктураОшибки.ВерсияФормата = "1.4";
	СтруктураОшибки.УИ = Строка(Новый УникальныйИдентификатор);
	СтруктураОшибки.ТипОшибки = "Ошибка сценария";

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

	СтруктураОшибки.Вставить("ИсходнаяИнформация", ИмяСценария + Символы.ПС + ОписаниеОшибки);

	ПорядокВоспроизведения = ПорядокВоспроизведения(ДанныеДляФормированияОшибкиСППР,
		РезультатПрохожденияТестовСценария, ИмяСценария, МассивТегов, ОписаниеОшибки);
	СтруктураОшибки.Вставить("ПорядокВоспроизведения", ПорядокВоспроизведения);

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

	СтруктураОбъектыМетаданных = Новый Структура;
	СтруктураОбъектыМетаданных.Вставить("ОбъектМетаданных", "");
	СтруктураОбъектыМетаданных.Вставить("УточнениеРасположения", УточнениеРасположения);
	СтруктураОшибки.ОбъектыМетаданных.Добавить(СтруктураОбъектыМетаданных);

	СистемнаяИнформация = Новый СистемнаяИнформация;

	СтруктураОшибки.Вставить("ВерсияПлатформы", СистемнаяИнформация.ВерсияПриложения);
	СтруктураОшибки.Вставить("КлиентОперативнаяПамять", СистемнаяИнформация.ОперативнаяПамять);
	СтруктураОшибки.Вставить("КлиентВерсияОС", СистемнаяИнформация.ВерсияОС);
	СтруктураОшибки.Вставить("КлиентПроцессор", СистемнаяИнформация.Процессор);
	СтруктураОшибки.Вставить("КлиентТипПлатформы", Строка(СистемнаяИнформация.ТипПлатформы));
	СтруктураОшибки.Вставить("КлиентИнформацияПрограммыПросмотра", СистемнаяИнформация.ИнформацияПрограммыПросмотра);
	СтруктураОшибки.Вставить("КлиентТекущаяДата", ТекущаяДатаСеанса());

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

					Если ДанныеФайла.Свойство("ШагСвязанныйСФайломИдСтроки") Тогда

						Если ДанныеДляФормированияОшибкиСППР.РегистрацияОшибки Тогда
							//Значит это скриншот добавлен при регистрации ошибки из секции Исключение
							Если ДанныеДляФормированияОшибкиСППР.ТекШагИдСтроки <> ДанныеФайла.ШагСвязанныйСФайломИдСтроки Тогда
								Продолжить;
							КонецЕсли;
						КонецЕсли;

					КонецЕсли;
				КонецЕсли;

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

	Если ФайлыМакетов <> Неопределено Тогда
		Для Каждого ИмяФайла Из ФайлыМакетов Цикл
			ИменаФайлов.Добавить(ИмяФайла);
		КонецЦикла;
	КонецЕсли;

	СтруктураОшибки.Вставить("ИменаФайлов", ИменаФайлов);
	СтруктураОшибки.Вставить("ВерсияПлатформы", СистемнаяИнформация.ВерсияПриложения);
	СтруктураОшибки.Вставить("СерверОперативнаяПамять", СистемнаяИнформация.ОперативнаяПамять);
	СтруктураОшибки.Вставить("СерверВерсияОС", СистемнаяИнформация.ВерсияОС);
	СтруктураОшибки.Вставить("СерверПроцессор", СистемнаяИнформация.Процессор);
	СтруктураОшибки.Вставить("СерверТипПлатформы", Строка(СистемнаяИнформация.ТипПлатформы));
	СтруктураОшибки.Вставить("СерверИнформацияПрограммыПросмотра", СистемнаяИнформация.ИнформацияПрограммыПросмотра);
	СтруктураОшибки.Вставить("ДатаОбнаружения", ТекущаяДатаСеанса());
	СтруктураОшибки.Вставить("ДостоверностьОбнаружения", "Высокая");

	СтруктураОшибки.ИмяКонфигурации = ДанныеДляФормированияОшибкиСППР.ИмяКонфигурацииСППР;
	СтруктураОшибки.ВерсияКонфигурации = ДанныеДляФормированияОшибкиСППР.ВерсияКонфигурацииСППР;

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

	ДобавитьЗначенияИзТеговСценария(СтруктураОшибки, МассивТегов);
	СтруктураОшибки.Вставить("ИмяСценария", ИмяСценария);

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();

	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СтруктураОшибки);

	Возврат ЗаписьXML.Закрыть();
КонецФункции

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

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

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

	Результат = МассивВСтрокуНаСервереБезКонтекста(КомпонентыРезультата, ,
		ДанныеДляФормированияОшибкиСППР.ЕстьПоддержкаФункцияРазложитьСтрокуВМассивПодстрок);

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

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

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

Процедура ДополнитьСтекомВызова(КомпонентыРезультата, ИмяСценария, МассивТегов)

	Если ТипЗнч(МассивТегов) <> Тип("Массив") Тогда
		Возврат;
	КонецЕсли;

	ИдентификаторСценария = ЗначениеИзТегаСценария(МассивТегов, "UIDСценария=");
	Если Не ЗначениеЗаполнено(ИдентификаторСценария) Тогда
		ИдентификаторСценария = "00000000-0000-0000-0000-000000000000";
	КонецЕсли;

	СтрокаСтека = ПодставитьПараметрыВСтрокуСервер("%1;0;%2;", ИмяСценария, ИдентификаторСценария);

	КомпонентыРезультата.Добавить("");
	КомпонентыРезультата.Добавить(НСтр("ru = 'Стек вызова:'"));
	КомпонентыРезультата.Добавить(СтрокаСтека);

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

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

Функция УточнениеРасположения(ДанныеДляФормированияОшибкиСППР, РезультатПрохожденияТестовСценария, ИмяСценария)

	КомпонентыРезультата = Новый Массив;
	КомпонентыРезультата.Добавить(ИмяСценария);
	ДополнитьРезультатомПрохожденияШагов(КомпонентыРезультата, РезультатПрохожденияТестовСценария);

	Результат = МассивВСтрокуНаСервереБезКонтекста(КомпонентыРезультата, ,
		ДанныеДляФормированияОшибкиСППР.ЕстьПоддержкаФункцияРазложитьСтрокуВМассивПодстрок);

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

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

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

[Assistant] Функция ТекстОшибкиXMLСППР(ДанныеДляФормированияОшибкиСППР, РезультатПрохожденияТестовСценария, КаталогВыгрузкиСППР, МассивТегов, ИмяСценария, ФайлыМакетов)


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

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

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

	ТекРодитель = СтрокаДерева;

	Пока Истина Цикл
		Если ТекРодитель = Неопределено Тогда
			Возврат Неопределено;
		КонецЕсли;

		Если ТекРодитель.ДопТип = "Контекст" Тогда
			ЭтоКонтекст = Истина;
			Прервать;
		КонецЕсли;

		Если ТекРодитель.Тип = "Сценарий" Тогда
			Прервать;
		КонецЕсли;

		Если ТекРодитель.Тип = "Пример" Тогда
			ЭтоПример = Истина;
			Прервать;
		КонецЕсли;

		ТекРодитель = ТекРодитель.ПолучитьРодителя();
	КонецЦикла;

	Возврат ТекРодитель.ИДСтроки;
КонецФункции

&НаКлиенте

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

		ПолучитьМассивСценариевДаннойФичи(СтрокаДерева, Массив);
	КонецЦикла;
КонецПроцедуры

&НаКлиенте

Процедура ВыполнитьФичу()
	Если Объект.ИдетВыполнениеСценариев Тогда
		Возврат;
	КонецЕсли;

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

	Объект.РежимВыполненияДанногоСценарияСТекущегоШага              = Ложь;
	Объект.РежимВыполненияДанногоСценарияСТекущегоШагаСПродолжением = Ложь;
	Объект.РежимВыполненияОдногоШага                                = Ложь;

	СтрокаФичи = Элементы.ДеревоТестов.ТекущиеДанные;
	Если СтрокаФичи = Неопределено Тогда
		Возврат;
	КонецЕсли;

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

	Массив     = Новый Массив;
	ПолучитьМассивСценариевДаннойФичи(СтрокаФичи, Массив);

	ВыполнитьСценарии(Массив);
КонецПроцедуры

&НаКлиенте

Процедура ОбновитьСтатусыКнопокСценариев(ОстановкаВыполнения = Ложь)
	Если Объект.ИспользоватьРедакторVanessaEditor Тогда
		Элементы.ФормаVanessaEditorСоздатьНовыйСценарий.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПодменюVanessaEditorЗагрузитьФичи.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorФормаПерейтиВДеревоШагов.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorПерезагрузить.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorСохранитьФайл.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorСохранитьФайлКак.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorВыполнитьСценарии.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorФормаПерезагрузитьИВыполнить.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorФормаВключитьВыключитьЗаписьВидео.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПанельVanessaEditorОзвучиваниеВыполненияСценария.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorSetBreakPoint.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorRemoveBreakPoints.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorПерейтиКСледующейОшибке.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorОткрытьПодключитьTestClient.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorНачатьЗаписьДействийПользователя.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorЗавершитьЗаписьДействийПользователя.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorКомментироватьСтрокиСценария.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorВыделитьСтрокиСценария.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorОткрытьСписокУроков.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorClipboardCut.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorClipboardCopy.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorClipboardPaste.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorEditUndo.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorEditRedo.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorОчиститьРаскраскуСтрок.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ГруппаVanessaEditorИнструменты.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorПоказатьСкрытьДеревоКаталогов.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ГруппаVanessaEditorНастройкиРедактора.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorПоказатьСкрытьДеревоGit.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ГруппаVanessaEditorСвернутьШаги.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ГруппаVanessaEditorПоискВТексте.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.VanessaEditorПеревестиТекстНаДругойЯзык.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
	Иначе
		Если НЕ ВыполнениеСценариевБезОткрытияФормы Тогда
			Если ОстановкаВыполнения Тогда
				Элементы.ВыполнитьСценарии.Заголовок = ЗаголовокКнопкиВыполнитьСценарии;
			ИначеЕсли Объект.ИдетВыполнениеСценариев Тогда
				Элементы.ВыполнитьСценарии.Заголовок = Локализовать("Выполняется...");
				Элементы.ОстановитьСценарии.Заголовок = ЗаголовокКнопкиОстановитьСценарии;
			Иначе
				Элементы.ВыполнитьСценарии.Заголовок = ЗаголовокКнопкиВыполнитьСценарии;
			КонецЕсли;

			Если ОстановкаВыполнения Тогда
				Элементы.ОстановитьСценарии.Заголовок = ЗаголовокКнопкиОстановитьСценарии;
			ИначеЕсли ОстановитьВыполнениеШагов И НЕ ОстановкаВыполнения Тогда
				//Элементы.ОстановитьСценарии.Заголовок = Локализовать("Останавливается...");
			Иначе
				Элементы.ОстановитьСценарии.Заголовок = ЗаголовокКнопкиОстановитьСценарии;
			КонецЕсли;
		КонецЕсли;

		Элементы.ФормаПерейтиВVanessaEditor.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ПодменюЗагрузитьФичи.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.Перезагрузить.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ВыполнитьСценарии.Доступность = НЕ Объект.ИдетВыполнениеСценариев;
		Элементы.ФормаПерезагрузитьИВыполнить.Доступность = НЕ Объект.ИдетВыполнениеСценариев;

	КонецЕсли;

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

&НаКлиенте

Функция СоздатьДанныеДляПоискаСтрокиШага(СтрокаДерева)
	Массив = Новый Массив;

	ТекРодитель = СтрокаДерева;
	Пока ТекРодитель <> Неопределено Цикл
		Массив.Вставить(0, ТекРодитель.ИдСтроки);
		ТекРодитель = ТекРодитель.ПолучитьРодителя();
	КонецЦикла;

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

&НаКлиенте

[Assistant] Функция ОпределитьИдСценарияПоСтрокеШагаКлиент(СтрокаДерева, ЭтоПример, ЭтоКонтекст)


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

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

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

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

		ТекстДиктораВШаге = ?(ТекущийШаг.Свойство("ТекстДиктораВШаге"),ТекущийШаг.ТекстДиктораВШаге,Неопределено);
		Если ЭтотШагНеИгнорироватьДляВидеоИнструкции(ТекущийШаг) Тогда
			Если Ванесса.ЭтоШагВидеовставкиКартинки(ТекущийШаг) Тогда
			// Хорошо бы через параметры, но не доступно здесь, поэтому через переменную (начиная с 19-го символа в имени шага с параметром [34- двойные кавычки]
				Если ТекущийШаг.Свойство("ПереданныеВШагТаблицы") И ТекущийШаг.ПереданныеВШагТаблицы.Количество() > 0 Тогда
					ТекстДиктораВШаге = ТекущийШаг.ЗначенияПараметров[1].Значение.Значение;
				иначе
                    ТекстДиктораВШаге = ОбработкаДопТекста(ТекущийШаг.Имя);
					ТекстДиктораВШаге = Сред(ТекстДиктораВШаге,_СтрНайти(НРег(ТекстДиктораВШаге),".png") + 5);
					ТекстДиктораВШаге = СокрЛП(СтрЗаменить(ТекстДиктораВШаге, Символ(34), ""));
					ТекстДиктораВШаге = ОбработкаДопТекста(ТекстДиктораВШаге);
				КонецЕсли;
			иначе
				// Для Шага ТекстДиктора
				ТекстДиктораВШаге = Сред(ТекущийШаг.Имя,19);
				ТекстДиктораВШаге = СокрЛП(СтрЗаменить(ТекстДиктораВШаге, Символ(34), ""));
				ТекстДиктораВШаге = ОбработкаДопТекста(ТекстДиктораВШаге);
			КонецЕсли;
			// Текст диктора отключает игнорирование в Автоинструкции , исключается из общей группы (становится временно текстом Группы),
			// подменяется свойства первого и последнего шага в группе [проверить, чтобы не поменялся на иной].
            ШагУточ.Вставить("ИгнорироватьШагВАвтоинструкции",Ложь);
			ШагУточ.Вставить("ВнутриГруппыКотораяРаботаетКакОдинШаг",Ложь);
			ШагУточ.Вставить("ПервыйВГруппеШагов",Истина);
			ШагУточ.Вставить("ПоследнийВГруппеШагов", Истина);
		КонецЕсли;
		ШагУточ.Вставить("ТекстДиктораВШаге",ТекстДиктораВШаге);
	КонецЕсли;
	//ДопТекст = ?(ТекущийШаг.Свойство("ДопТекст"),ТекущийШаг.ДопТекст,Неопределено);
    //+++ Аналогичный код есть при заполнении ЛогаИнструкцииHTML
	ДопТекст = "";
	//Если ТекущийШаг.Свойство("ШагСПараметрамиВТаблице") И ТекущийШаг.ШагСПараметрамиВТаблице = Истина Тогда
	// 	Для каждого СтрПараметрыТаблицы Из ТекущийШаг.ПараметрыТаблицы Цикл
	//		ДопТекст = ДопТекст + ?(ДопТекст = "","","\n") + ОбработкаДопТекста(СтрПараметрыТаблицы);
	//  	КонецЦикла;
	//КонецЕсли;
	//Если ДопТекст = "" тогда
	//	Если ТекущийШаг.Свойство("ПереданныеВШагТаблицы") и ТекущийШаг.ПереданныеВШагТаблицы.Количество() > 0 тогда;
	//		//+++ ЦВ_ПР В цикле неверно работают ПереданныеВШагТаблицы (Хранят 1-е значение, а не последнее - Почему?)
	//		Если ТипЗнч(ТекущийШаг.ПереданныеВШагТаблицы[0][0])= Тип("Соответствие") тогда
	//			Попытка
	//   				 ДопТекст = ТекущийШаг.ПереданныеВШагТаблицы[0][0].получить("HTML").Тело.ТекстовоеСодержимое;
	//			Исключение
	//				ДопТекст = "";
	//			КонецПопытки;
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ЗаполнитьРезультатамиМассивСценариевДляВыполнения(ИдСценария, ИдШага,ТекущийШаг, РезультатШага, РезультатыТестов)
    // Актуально только для автодокументирования
	Если Не (Объект.СоздаватьИнструкциюВидео или Объект.СоздаватьИнструкциюHTML или Объект.СоздаватьИнструкциюMarkdown) Тогда
		Возврат;
	КонецЕсли;
    // Глубокое копирование передает значения, а не ссылки, чтобы не ловить ошибки "искажения данных" в цикле. Истина в функции дополнительно вычислит переменные
	// Возможно функцию нужно уточнять с учетом реального использования
	ШагУточ = ГлубокоеКопирование(ТекущийШаг,Истина);
	// Имя шага с переменными и выражениями с фигурными скобками были заменены, сохраним его (может пригодится)
	ШагУточ.Вставить("ИмяСВычислениями",ШагУточ.Имя);
	// Сохраняем, некоторые поля без вычислений, если важно оставить как было
	ШагУточ.Вставить("Имя",ГлубокоеКопирование(ТекущийШаг.Имя, Ложь));

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

		ТекстДиктораВШаге = ?(ТекущийШаг.Свойство("ТекстДиктораВШаге"),ТекущийШаг.ТекстДиктораВШаге,Неопределено);
		Если ЭтотШагНеИгнорироватьДляВидеоИнструкции(ТекущийШаг) Тогда
			Если Ванесса.ЭтоШагВидеовставкиКартинки(ТекущийШаг) Тогда
			// Хорошо бы через параметры, но не доступно здесь, поэтому через переменную (начиная с 19-го символа в имени шага с параметром [34- двойные кавычки]
				Если ТекущийШаг.Свойство("ПереданныеВШагТаблицы") И ТекущийШаг.ПереданныеВШагТаблицы.Количество() > 0 Тогда
					ТекстДиктораВШаге = ТекущийШаг.ЗначенияПараметров[1].Значение.Значение;
				иначе
                    ТекстДиктораВШаге = ОбработкаДопТекста(ТекущийШаг.Имя);
					ТекстДиктораВШаге = Сред(ТекстДиктораВШаге,_СтрНайти(НРег(ТекстДиктораВШаге),".png") + 5);
					ТекстДиктораВШаге = СокрЛП(СтрЗаменить(ТекстДиктораВШаге, Символ(34), ""));
					ТекстДиктораВШаге = ОбработкаДопТекста(ТекстДиктораВШаге);
				КонецЕсли;
			иначе
				// Для Шага ТекстДиктора
				ТекстДиктораВШаге = Сред(ТекущийШаг.Имя,19);
				ТекстДиктораВШаге = СокрЛП(СтрЗаменить(ТекстДиктораВШаге, Символ(34), ""));
				ТекстДиктораВШаге = ОбработкаДопТекста(ТекстДиктораВШаге);
			КонецЕсли;
			// Текст диктора отключает игнорирование в Автоинструкции , исключается из общей группы (становится временно текстом Группы),
			// подменяется свойства первого и последнего шага в группе [проверить, чтобы не поменялся на иной].
            ШагУточ.Вставить("ИгнорироватьШагВАвтоинструкции",Ложь);
			ШагУточ.Вставить("ВнутриГруппыКотораяРаботаетКакОдинШаг",Ложь);
			ШагУточ.Вставить("ПервыйВГруппеШагов",Истина);
			ШагУточ.Вставить("ПоследнийВГруппеШагов", Истина);
		КонецЕсли;
		ШагУточ.Вставить("ТекстДиктораВШаге",ТекстДиктораВШаге);
	КонецЕсли;
	//ДопТекст = ?(ТекущийШаг.Свойство("ДопТекст"),ТекущийШаг.ДопТекст,Неопределено);
    //+++ Аналогичный код есть при заполнении ЛогаИнструкцииHTML
	ДопТекст = "";
	//Если ТекущийШаг.Свойство("ШагСПараметрамиВТаблице") И ТекущийШаг.ШагСПараметрамиВТаблице = Истина Тогда
	// 	Для каждого СтрПараметрыТаблицы Из ТекущийШаг.ПараметрыТаблицы Цикл
	//		ДопТекст = ДопТекст + ?(ДопТекст = "","","\n") + ОбработкаДопТекста(СтрПараметрыТаблицы);
	//  	КонецЦикла;
	//КонецЕсли;
	//Если ДопТекст = "" тогда
	//	Если ТекущийШаг.Свойство("ПереданныеВШагТаблицы") и ТекущийШаг.ПереданныеВШагТаблицы.Количество() > 0 тогда;
	//		//+++ ЦВ_ПР В цикле неверно работают ПереданныеВШагТаблицы (Хранят 1-е значение, а не последнее - Почему?)
	//		Если ТипЗнч(ТекущийШаг.ПереданныеВШагТаблицы[0][0])= Тип("Соответствие") тогда
	//			Попытка
	//   				 ДопТекст = ТекущийШаг.ПереданныеВШагТаблицы[0][0].получить("HTML").Тело.ТекстовоеСодержимое;
	//			Исключение
	//				ДопТекст = "";
	//			КонецПопытки;
	//		КонецЕсли;
	//		Если ДопТекст = "" тогда
	//			// +++ ЦВ_ПР Пока упрощенное чтение из 1-й колонки
	//
	//			Если ЭтоШагВидеовставкиКартинки(ТекущийШаг) Тогда
	//				ДопТекст = ТекущийШаг.ЗначенияПараметров[1].Значение.Значение;
	//			иначе
	//				Попытка
	//   					ДопТекст = ТекущийШаг.ПереданныеВШагТаблицы[0][0].Кол1;
	//				Исключение
	//    				ДопТекст = ""; // или другое значение по умолчанию
	//				КонецПопытки
	//			КонецЕсли;
	//		КонецЕсли;
	//	КонецЕсли;
	//КонецЕсли;
	//ДопТекст = ОбработкаДопТекста(ДопТекст);
	//--- ЦВ_ПР 27.06.2025 конец вставки

	ШагУточ.Вставить("ДопТекст",ДопТекст);
	Если ЗначениеЗаполнено(ШагУточ.ДопТекст) и не (ЭтотШагНеИгнорироватьДляВидеоИнструкции(ТекущийШаг)) тогда
		// 30.06.2025 Заменить СтрокаРеальнойПроцедуры = "ТекстДиктора"
		// Если передали не пустой текст, значит меняем признаки 1-й шаг в группе не исключается для обработки HTML, для Видео - игнорируем
		// Последний шаг в группе актуален для скриншотов (после него скриншот делается)
		ШагУточ.Вставить("ИгнорироватьШагВАвтоинструкции",Истина);
		ШагУточ.Вставить("ВнутриГруппыКотораяРаботаетКакОдинШаг",Ложь);
		//ШагУточ.Вставить("ПервыйВГруппеШагов",Истина);
		ШагУточ.Вставить("ПоследнийВГруппеШагов", Истина);
	КонецЕсли;
    // 09.07.2025 Дополним обработку Вставки слайдов в HTML
	Если ЭтотШагНеИгнорироватьДляHTMLИнструкции(ТекущийШаг) тогда
		// 30.06.2025 Заменить СтрокаРеальнойПроцедуры = "ТекстДиктора"
		// Если передали не пустой текст, значит меняем признаки 1-й шаг в группе не исключается для обработки HTML, для Видео - игнорируем
		// Последний шаг в группе актуален для скриншотов (после него скриншот делается)
		ШагУточ.Вставить("ИгнорироватьШагВАвтоинструкции",Ложь);
		ШагУточ.Вставить("ВнутриГруппыКотораяРаботаетКакОдинШаг",Ложь);
		//ШагУточ.Вставить("ПервыйВГруппеШагов",Истина);
		ШагУточ.Вставить("ПоследнийВГруппеШагов", Истина);
	КонецЕсли;

	Если ТекущийШаг.Свойство("ДопТип") и (ТекущийШаг.ДопТип = "Цикл" ИЛИ ТекущийШаг.ДопТип = "Условие" ИЛИ ТекущийШаг.ДопТип = "УсловиеИначеЕсли") тогда
		//ЦВ_ПР Исключаем озвучку шагов начала Цикла и аналогичных
		ШагУточ.Вставить("ИгнорироватьШагВАвтоинструкции",Истина);
	КонецЕсли;

	//ЦВ_ПР Меняем текст , если есть чем
	ТекстИнструкция ="";
	Если ШагУточ.Свойство("ДопТекст") И ЗначениеЗаполнено(ШагУточ.ДопТекст) тогда
		ТекстИнструкция = ШагУточ.ДопТекст;
	КонецЕсли;
	Если ШагУточ.Свойство("ТекстДиктораВШаге") И ЗначениеЗаполнено(ШагУточ.ТекстДиктораВШаге) тогда
		ТекстИнструкция = ШагУточ.ТекстДиктораВШаге;
	КонецЕсли;
	Если ЗначениеЗаполнено(ТекстИнструкция) тогда
		//+++ ЦВ_ПР 22.10.2025 нужно учесть тег StartRecordVideo, который включает принудительно запись Видео и нежелательную озвучку названия шага в тексте отключим
		Если ШагУточ.Свойство("ДирективныйЗапускЗаписиВидео") и ШагУточ.ДирективныйЗапускЗаписиВидео Тогда
			ШагУточ.Вставить("ТекстИнструкция", ?(ШагУточ.Свойство("ТекстДиктораВШаге") И ЗначениеЗаполнено(ШагУточ.ТекстДиктораВШаге),ШагУточ.ТекстДиктораВШаге,""));
		иначе
			ШагУточ.Вставить("ТекстИнструкция",ТекстИнструкция);
		КонецЕсли;
		//--- ЦВ_ПР 22.10.2025
	КонецЕсли;

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

КонецПроцедуры
//--- ЦВ_ПР 18.06.2025
//+++ ЦВ_ПР 24.06.2025 Обработка строки Текста с учетом переменных и фигурных скобок
&НаКлиенте


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

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

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

	СтрДоп = СтрЗаменить(СтрокаДопТекста, "|", "");
	СтрДоп = СокрЛП(СтрЗаменить(СтрДоп, "'", ""));
	Если Найти(СтрДоп, "$") > 0 Тогда
		ВТаблицахИспользовалисьПеременные = Истина;
	КонецЕсли;
	СтрДоп = ПолучитьЗначениеИзКонтекстаЕслиЭтоВозможно(СтрДоп, Ложь);
	Если Найти(СтрДоп,"$") > 0 Тогда
		СтрДоп = ПодставитьПеременныеВСтроку(СтрДоп);
	КонецЕсли;
	Если Найти(СтрДоп, "{") > 0 Тогда
 		ДанныеПоПростымПеременным = 0; // Из ДанныеПоПростымПеременнымПоТекущемуСценарию() может вернуться Неопределено, поэтому инициалиция нулём
		ДанныеПоПеременныхВТаблицах = 0; // Тоже самое
		Если МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ЕстьСекцияПеременные ИЛИ Объект.ВычислятьВыраженияВФигурныхСкобках Тогда
			СтрДоп = ВычислитьИнлайнВыражениеЕслиЭтоВозможно(СтрДоп, ДанныеПоПростымПеременным, ДанныеПоПеременныхВТаблицах, МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ЕстьСекцияПеременные);
		КонецЕсли;
	КонецЕсли;
	СтрокаДопТекста = СтрДоп;
	Возврат СтрокаДопТекста;
КонецФункции
//--- ЦВ_ПР 24.06.2025

&НаКлиенте

Процедура ДобавитьСтрокуКакТекст(ДокументHTML, УзелРодитель, Стр, ЭтоШагБезСкриншота)

	УзелАбзац = ДокументHTML.СоздатьЭлемент("p");
	ТекстовыйУзел = ДокументHTML.СоздатьТекстовыйУзел(Стр);

	ЕстьВертЧерта = Найти(Стр, "|") > 0;

	Если ЕстьВертЧерта Тогда
		УзелКод = ДокументHTML.СоздатьЭлемент("pre");
		УзелКод.ДобавитьДочерний(ТекстовыйУзел);
		УзелАбзац.ДобавитьДочерний(УзелКод);
		УзелРодитель.ДобавитьДочерний(УзелАбзац);
	ИначеЕсли ЭтоШагБезСкриншота Тогда
		УзелАбзац.ДобавитьДочерний(ТекстовыйУзел);
		УзелРодитель.ДобавитьДочерний(УзелАбзац);
	КонецЕсли;

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

&НаКлиенте

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

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

		Ном = Ном + 1;

		Если Стр = "--окончание заголовка--" Тогда
			СтрокаОкончанияЗаголовка = Ном;
			Прервать;
		КонецЕсли;

		ЗаголовокФичи.Добавить(Стр);
	КонецЦикла;

	Текст.Закрыть();

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

&НаСервере

Функция ПолучитьСтилиCSSИзМакета(ИмяМакета);

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

	Возврат ТекстДокумента;

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

&НаКлиенте

Функция ПолучитьДокументHTML(СтрокаHTML)

	ЧтениеHTML = Новый ЧтениеHTML;
	ЧтениеHTML.УстановитьСтроку(СтрокаHTML);

	ПостроительDOM = Новый ПостроительDOM;
	ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
	ЧтениеHTML.Закрыть();

	Возврат ДокументHTML;

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

&НаКлиенте

Процедура ПроцедураПереместитьФайл(Знач Стр1, Знач Стр2)
	ПереместитьФайлКомандаСистемы(Стр1, Стр2);
КонецПроцедуры

#Область АссертыСлужебное
// Портирован блок ассертов из проекта xUnitFor1C (https://github.com/xDrivenDevelopment/xUnitFor1C)
// взят релиз 3.0.0.3
// { МЕТОДЫ ДЛЯ ПРОВЕРКИ ЗНАЧЕНИЙ (assertions).

&НаКлиенте

Функция ФорматДСО(ДопСообщениеОшибки)
	Если ДопСообщениеОшибки = "" Тогда
		Возврат "";
	КонецЕсли;

	Возврат Символы.ПС + " <" + ДопСообщениеОшибки + ">";
КонецФункции

&НаКлиенте

Функция СтруктураОшибкаАссерта(СообщениеОшибки)
	Возврат Новый Структура("БылаОшибка,ОписаниеОшибки,ЗначениеExpected,ЗначениеActual",
	    Истина, СообщениеОшибки, ЗначениеExpected, ЗначениеActual);
КонецФункции

&НаКлиенте

Функция ВызватьОшибкуПроверки(СообщениеОшибки)

	Префикс = "[" + СтатусыРезультатаТестирования.ОшибкаПроверки + "]";
	ТекстСообщения = Префикс + " " + СообщениеОшибки;
	Если НЕ ОстановитьВыполнениеШагов Тогда
		ВызватьИсключение ТекстСообщения;
	Иначе
		Если ОшибкиАссертов = Неопределено Тогда
			ОшибкиАссертов = Новый Массив;
		КонецЕсли;

		СтруктураОшибкаАссерта = СтруктураОшибкаАссерта(СообщениеОшибки);
		ОшибкиАссертов.Добавить(СтруктураОшибкаАссерта);
		Возврат СтруктураОшибкаАссерта;
	КонецЕсли;

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

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

Функция ПараметрыСтрокой(Знач Параметры, Знач ИмяПеременной = "Параметры")

	ПараметрыСтрока = "";
	Если Параметры <> Неопределено Тогда
		Если ТипЗнч(Параметры) = Тип("Массив") Тогда
			Для Индекс = 0 По Параметры.ВГраница() Цикл
				ПараметрыСтрока = ПараметрыСтрока + ", " + ИмяПеременной + "[" + Формат(Индекс, "ЧН=0; ЧГ=0") + "]";
			КонецЦикла;
			ПараметрыСтрока = Сред(ПараметрыСтрока, 3);
		Иначе
			ПараметрыСтрока = ИмяПеременной;
		КонецЕсли;
	КонецЕсли;

	Возврат ПараметрыСтрока;

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

// Только для внутреннего использования
&НаСервереБезКонтекста

Функция ОпределитьКоличествоПередаваемыхТаблиц(СтрокаДерева)
	Если СтрокаДерева.ШагСПараметрамиВТаблице <> Истина Тогда
		Возврат 0;
	КонецЕсли;

	Количество = 1;
	Для Каждого ПодчиненнаяСтрокаДерева Из СтрокаДерева.Строки Цикл
		Если Не ЗначениеЗаполнено(ПодчиненнаяСтрокаДерева.Имя) Тогда
			Количество = Количество + 1;
		КонецЕсли;
	КонецЦикла;

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

// Устанавливает ожидаемое и реальное значение для ассертов.
//
// Параметры:
//   ОжидаемоеЗначнеие - Произвольный - Ожидаемое значение.
//   РеальноеЗначение  - Произвольный - Реальное значение.
//
&НаКлиенте

Процедура ОбработатьAssertОжидаемоеРеальноеЗначение(ОжидаемоеЗначнеие, РеальноеЗначение) Экспорт
	ОшибкаAssert     = Истина;
	ЗначениеActual   = РеальноеЗначение;
	ЗначениеExpected = ОжидаемоеЗначнеие;
КонецПроцедуры

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

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

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

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

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

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

&НаСервере

Процедура ПолучитьСписокФичПоДеревуИСоздатьEPFПоМассивуФич(СтруктураПараметров, МассивФич, МассивШагов)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	Дерево = ОбъектСервер.ДеревоТестов;

	ДобавитьИменаФайловФичИзДереваВМассив(Дерево.Строки, МассивФич, МассивШагов);

	СтруктураПараметров.Вставить("КонтекстVanessaBehavoir", ОбъектСервер);

	СтруктураПараметров.КонтекстVanessaBehavoir = "";
КонецПроцедуры

&НаКлиенте

Процедура ВыполнитьКомандуОС(Стр)
	#Если НЕ ВебКлиент Тогда
	КомандаСистемы(Стр);
	#КонецЕсли
КонецПроцедуры

&НаКлиенте

[Assistant] Функция ОбработкаДопТекста(знач СтрокаДопТекста)


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

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

Функция ИмяФункции(СтруктураОписанияEpf)
	#Если НЕ ВебКлиент Тогда

	ИмяФайла = СтруктураОписанияEpf.ИмяФайлаEPF;
	ФайлEPF = Новый Файл(ИмяФайла);

	ГенерироватьУФ      = Объект.ГенерироватьУФ;
	КаталогИнструментов = Объект.КаталогИнструментов;
	ЭтоУФ               = Истина;

	Попытка

		ВременныйКаталогБазы = ПолучитьИмяВременногоФайла();
		СоздатьКаталогКомандаСистемы(ВременныйКаталогБазы);
		ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
		ИмяФайлаOUT = ПолучитьИмяВременногоФайла("txt");
		КомандаСистемы = """" + ДополнитьСлешВПуть(Объект.ВерсияПлатформыДляГенерацииEPF)
			+ ИмяИсполняемогоФайлаТолстыйКлиент + """ CREATEINFOBASE File="""  + ВременныйКаталогБазы +  """ /out """ + ИмяФайлаOUT + """ > """ + ИмяФайлаЛога + """";
		Отладка(КомандаСистемы);
		ВыполнитьКомандуОСБезПоказаЧерногоОкна(КомандаСистемы);
		Если НЕ ФайлСуществуетКомандаСистемы(ВременныйКаталогБазы + "/1Cv8.1CD") Тогда
			СообщитьПользователю(Локализовать("Файл EPF не создан. Не смог создать каталог временной базы."));
			ВывестиТекстФайлаЛога(ИмяФайлаЛога);
			ВывестиТекстФайлаЛога(ИмяФайлаOUT, "");

			СообщитьПользователю (ПодставитьПараметрыВСтроку(
				Локализовать("Проверьте работу команды <%1>"),
				КомандаСистемы
			));
			Возврат Неопределено;
		КонецЕсли;

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

		ПутьКИсходникам = ПолучитьИмяВременногоФайла();
		СоздатьКаталогКомандаСистемы(ПутьКИсходникам);

		ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
		ИмяФайлаOUT = ПолучитьИмяВременногоФайла("txt");

		КомандаСистемы = """" + ДополнитьСлешВПуть(Объект.ВерсияПлатформыДляГенерацииEPF)
			+ ИмяИсполняемогоФайлаТолстыйКлиент + """ DESIGNER /F """ + ВременныйКаталогБазы + """ /DumpExternalDataProcessorOrReportToFiles  """
			+ ПутьКИсходникам + """ """ + СтруктураОписанияEpf.ИмяФайлаEPF + """ /out """ + ИмяФайлаOUT + """ > """ + ИмяФайлаЛога + """";
		Отладка(КомандаСистемы);
		ВыполнитьКомандуОСБезПоказаЧерногоОкна(КомандаСистемы);

		СписокКаталогов = Новый СписокЗначений;
		СписокФайлов    = Новый СписокЗначений;

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

		ФайлXML = СписокФайлов[0].Значение;
		СтруктураОписанияEpf.Вставить("РеальноеИмяОбработки", ФайлXML.ИмяБезРасширения);

		СтруктураОписанияEpf.КаталогИсходников = ПутьКИсходникам;
		Если ЭтоУФ Тогда
			СтруктураОписанияEpf.ВременноеИмяМодуля = ПутьКИсходникам + "/" + ФайлXML.ИмяБезРасширения + "/Forms/Форма/Ext/Form/Module.bsl";
		Иначе
			СтруктураОписанияEpf.ВременноеИмяМодуля = ПутьКИсходникам + "/" + ФайлXML.ИмяБезРасширения + "/Ext/ObjectModule.bsl";
		КонецЕсли;

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

		ОчиститьСодержимоеКаталога(ВременныйКаталогБазы);

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

	#КонецЕсли
КонецФункции

&НаКлиенте

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

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

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

Функция ЗагрузитьТелоМодуляВТаблицуЗначенийСервер(Знач ДвоичныеДанные, Знач ШагСтрокДляМодуля)
	ПутьКФайлу = ПолучитьИмяВременногоФайла("txt");

	ДвоичныеДанные.Записать(ПутьКФайлу);

	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("НомСтр");
	Тзн.Колонки.Добавить("Стр");

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

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

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

		НомСтр = НомСтр + ШагСтрокДляМодуля;

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

	Текст.Закрыть();

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

&НаКлиенте

Функция ЗагрузитьТелоМодуляВТаблицуЗначений(ПутьКФайлу)
	ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
	Возврат ЗагрузитьТелоМодуляВТаблицуЗначенийСервер(ДвоичныеДанные, ШагСтрокДляМодуля);
КонецФункции

&НаСервере

Процедура ДобавитьНачальноеЗаполнениеВМодульСервер(ТелоМодуля, Знач ШагСтрокДляМодуля, Знач ГенерироватьУФ,
		Знач ДвДанныеvbFeatureReader, Знач знСоздаватьОбластиПриГенерацииКода)

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

&НаКлиенте

Процедура ДобавитьНачальноеЗаполнениеВМодуль(ТелоМодуля, ШагСтрокДляМодуля, ГенерироватьУФ,
		ДвДанныеvbFeatureReader, ЗнСоздаватьОбластиПриГенерацииКода)

	ДобавитьНачальноеЗаполнениеВМодульСервер(ТелоМодуля, ШагСтрокДляМодуля, ГенерироватьУФ,
		ДвДанныеvbFeatureReader, ЗнСоздаватьОбластиПриГенерацииКода);
КонецПроцедуры

&НаКлиенте

Функция НайтиФайлВМассивеФайлов(МассивФайлов, ИмяФайла)
	Для каждого Элем Из МассивФайлов Цикл

		Если ТипЗнч(Элем) = Тип("Структура") Тогда
			Файл = Элем.Файл;
		Иначе
			Файл = Элем;
		КонецЕсли;

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

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

&НаСервере

Функция ДанныеСлужебныйКешГенерацияEPF()
	ОбъектСервер   = РеквизитФормыВЗначение("Объект");
	ТекстовыйМакет = ОбъектСервер.ПолучитьМакет("МакетСлужебныйКеш");
	Строка         = ТекстовыйМакет.ПолучитьТекст();
	Возврат ЗначениеИзСтрокиВнутр(Строка).МассивФайловTemplateEpfUF;
КонецФункции

&НаКлиенте

[Assistant] Функция РаспаковатьEPF(СтруктураОписанияEpf)


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

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

Функция ИмяФункции(Знач Стр)

	Стр = СтрЗаменить(Стр, " ", "_");
	Стр = СтрЗаменить(Стр, "`", "");
	Стр = СтрЗаменить(Стр, "~", "");
	Стр = СтрЗаменить(Стр, "'", "");
	Стр = СтрЗаменить(Стр, ".", "");
	Стр = СтрЗаменить(Стр, ",", "");
	Стр = СтрЗаменить(Стр, ":", "");
	Стр = СтрЗаменить(Стр, ";", "");
	Стр = СтрЗаменить(Стр, "-", "_");
	Стр = СтрЗаменить(Стр, "+", "");
	Стр = СтрЗаменить(Стр, "/", "");
	Стр = СтрЗаменить(Стр, "\", "");
	Стр = СтрЗаменить(Стр, "=", "");
	Стр = СтрЗаменить(Стр, "!", "");
	Стр = СтрЗаменить(Стр, "@", "");
	Стр = СтрЗаменить(Стр, "#", "");
	Стр = СтрЗаменить(Стр, "$", "");
	Стр = СтрЗаменить(Стр, "%", "");
	Стр = СтрЗаменить(Стр, "^", "");
	Стр = СтрЗаменить(Стр, "&", "");
	Стр = СтрЗаменить(Стр, "*", "");
	Стр = СтрЗаменить(Стр, "(", "");
	Стр = СтрЗаменить(Стр, ")", "");
	Стр = СтрЗаменить(Стр, "№", "");
	Стр = СтрЗаменить(Стр, "?", "");
	Стр = СтрЗаменить(Стр, "<", "");
	Стр = СтрЗаменить(Стр, ">", "");

	Если Лев(Стр, 1) = "0"
		Или Лев(Стр, 1) = "1"
		Или Лев(Стр, 1) = "2"
		Или Лев(Стр, 1) = "3"
		Или Лев(Стр, 1) = "4"
		Или Лев(Стр, 1) = "5"
		Или Лев(Стр, 1) = "6"
		Или Лев(Стр, 1) = "7"
		Или Лев(Стр, 1) = "8"
		Или Лев(Стр, 1) = "9" Тогда
		Стр = "_" + Стр;
	КонецЕсли;

	Возврат Стр;

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

&НаКлиенте

Процедура ЗаменитьСтрокиВФайлеОсновыОбработки(ПутьКИсходникам, ИмяОбработки)

	МассивФайлов = Новый Массив;
	МассивФайлов.Добавить(Новый Файл(ПутьКИсходникам + "/" + ИмяОбработки + ".xml"));
	МассивФайлов.Добавить(Новый Файл(ПутьКИсходникам + "/" + ИмяОбработки +  "/Forms/Форма/Ext/Form.xml"));

	Для Каждого Файл Из МассивФайлов Цикл
		Если НЕ ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
			Продолжить;
		КонецЕсли;

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

		ВременноеИмяФайла = Файл.ПолноеИмя + "_Temp";
		ЗТ = Новый ЗаписьТекста(ВременноеИмяФайла, "UTF-8", , Истина);
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;

			Стр = СтрЗаменить(Стр, "<Name>Обработка</Name>", "<Name>" + ИмяОбработки + "</Name>");
			Стр = СтрЗаменить(Стр, "<v8:content>Обработка</v8:content>", "<v8:content>" + ИмяОбработки + "</v8:content>");
			Стр = СтрЗаменить(Стр, "ExternalDataProcessor.Обработка.", "ExternalDataProcessor." + ИмяОбработки + ".");
			Стр = СтрЗаменить(Стр, "ExternalDataProcessorObject.Обработка", "ExternalDataProcessorObject." + ИмяОбработки);

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

		ЗТ.Закрыть();
		Текст.Закрыть();
		Текст = "";

		УдалитьФайлыКомандаСистемы(Файл.ПолноеИмя);
		ПереместитьФайлКомандаСистемы(ВременноеИмяФайла, Файл.ПолноеИмя);
	КонецЦикла;

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

&НаКлиенте

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

&НаКлиенте

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

	СообщитьПользователю(Текст.Прочитать());

	Текст.Закрыть();
КонецПроцедуры

&НаКлиенте

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


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

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

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

	Возврат ГлавноеОкноТестируемого;
КонецФункции

&НаКлиенте

Процедура УдалитьИзПодключенныеTestClientПрофильКлиентаТестированияПоИмени(ИмяПрофиля)

	ПодключенныеTestClient = ОбъектКонтекстСохраняемый.ПодключенныеTestClient;

	НужныйИД = Неопределено;
	Для Ккк = 0 По ПодключенныеTestClient.Количество() - 1 Цикл
		Элем = ПодключенныеTestClient[Ккк];
		Если Элем.Имя = ИмяПрофиля Тогда
			НужныйИД = Ккк;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Если НужныйИД <> Неопределено Тогда
		ПодключенныеTestClient.Удалить(НужныйИД);
	КонецЕсли;

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

&НаКлиенте

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

	УдалитьИзПодключенныеTestClientПрофильКлиентаТестированияПоИмени(ДанныеЗапускаКлиентаТестирования.Имя);

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

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

&НаКлиенте

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


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

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

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

	Если Лев(НРег(АдресТекущейОбласти), 1) = "r" Тогда
		НачСтр1 = -1;
		НачКол1 = -1;
		КолСтр1 = -1;
		КолКол1 = -1;
		ПолучитьПараметрыОбластиМакета(АдресТекущейОбласти, НачСтр1, НачКол1, КолСтр1, КолКол1);

		НачСтр2 = -1;
		НачКол2 = -1;
		КолСтр2 = -1;
		КолКол2 = -1;
		ПолучитьПараметрыОбластиМакета(Адрес, НачСтр2, НачКол2, КолСтр2, КолКол2);
		Если НачСтр1 > НачСтр2 Тогда
			Возврат Ложь; // значит АдресТекущейОбласти не находится внутри Адрес
		КонецЕсли;
		Если НачКол1 > НачКол2 Тогда
			Возврат Ложь; // значит АдресТекущейОбласти не находится внутри Адрес
		КонецЕсли;
		Если КолСтр1 < КолСтр2 Тогда
			Возврат Ложь; // значит АдресТекущейОбласти не находится внутри Адрес
		КонецЕсли;
		Если КолКол1 < КолКол2 Тогда
			Возврат Ложь; // значит АдресТекущейОбласти не находится внутри Адрес
		КонецЕсли;

	КонецЕсли;

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

&НаКлиенте

Функция СформироватьАдресЯчейки(НомерСтроки, НомерКолонки)
	Возврат "R" + Формат(НомерСтроки, "ЧГ=; ЧН=0") + "C" + Формат(НомерКолонки, "ЧГ=; ЧН=0");
КонецФункции

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

Функция МакетИзТекстаXML(Знач Строка)

    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(Строка);
    ЧтениеXML.Прочитать();

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

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

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

&НаКлиенте

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

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

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

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

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

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

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

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

	Если НадоСчитатьОбласть Тогда
		Возврат ОставитьЧастьМакетаСогласноПараметровЧтенияМакета(МакетИзТекстаXML(ПредставлениеДанных), ДопПараметры.НачСтр,
			ДопПараметры.НачКол, ДопПараметры.КолСтр, ДопПараметры.КолКол);
	Иначе
		Возврат МакетИзТекстаXML(ПредставлениеДанных);
	КонецЕсли;

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

&НаКлиенте

[Assistant] Функция ПерейтиВТабДокTestClientКЯчейке(ЭлементФормы, АдресТекущейОбласти, Адрес)


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

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

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

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

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

	Если НЕ ЭтоЗаголовокОкнаМодальногоДиалога(АктивноеОкно.Заголовок) Тогда
		Возврат Ложь;
	КонецЕсли;

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

	sleep(2);

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

&НаКлиенте

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

	СделатьСкриншотыВсехОконКомпонентаПродолжение();
КонецПроцедуры

&НаКлиенте

Процедура ОпределитьСвойстваПроцессаИСделатьСкриншотЕслиНеобходимоОбработкаОповещения(РезультатВызова, ПараметрыВызова, ДополнительныеПараметры) Экспорт

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

	Данные = ПрочитатьСтрокуJSON(РезультатВызова);
	Если ТипЗнч(Данные) = Тип("Структура") Тогда
		Если Найти(НРег(Данные.Name),"1cv8") > 0 ИЛИ ЭтоДополнительныйПроцессДляСнятиеСкриншотов Тогда

			МассивФайлов = Новый Массив;
			ПараметрыСкриншотов = Новый Структура;
			ПараметрыСкриншотов.Вставить("ИмяФайла",МассивФайлов);
			ПараметрыСкриншотов.Вставить("ProcessId",Данные.ProcessId);
			ПараметрыСкриншотов.Вставить("ИмяПроцедуры","ОпределитьСвойстваПроцессаИСделатьСкриншотЕслиНеобходимо");
			ПараметрыСкриншотов.Вставить("ЭтоДополнительныйПроцессДляСнятиеСкриншотов",ЭтоДополнительныйПроцессДляСнятиеСкриншотов);
			СделатьСкриншотКомпонента(ПараметрыСкриншотов);
			Возврат;

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

&НаКлиенте

Процедура СнятьСкриншотыОтдельныеПроцессы()

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

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

&НаКлиенте

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

	ДанныеСпискаПроцессов = ПрочитатьСтрокуJSON(РезультатВызова);
	МассивСтрокПоискаПроцессов = _СтрРазделить(СокрЛП(Объект.ПроцессыДляСнятияСкриншотов), ";");

	ИдДанныеСпискаПроцессов = -1;
	Если ТипЗнч(ДанныеСпискаПроцессов) = Тип("Массив") Тогда
		ПроцессыДляСнятиеСкриншотов = Новый Массив;
		Для Каждого ДанныеПроцесса Из ДанныеСпискаПроцессов Цикл
			Для Каждого ТекСтрокаПоиска Из МассивСтрокПоискаПроцессов Цикл
				Если НЕ ДанныеПроцесса.Свойство("CommandLine") Тогда
					Продолжить;
				КонецЕсли;

				Если Найти(ТекСтрокаПоиска, "*") > 0 Тогда
					Если СтрокаСоответствуетШаблону(НРег(ДанныеПроцесса.CommandLine), НРег(ТекСтрокаПоиска)) Тогда
						ПроцессыДляСнятиеСкриншотов.Добавить(ДанныеПроцесса);
					КонецЕсли;
				Иначе
					Если Найти(НРег(ДанныеПроцесса.CommandLine), НРег(ТекСтрокаПоиска)) > 0 Тогда
						ПроцессыДляСнятиеСкриншотов.Добавить(ДанныеПроцесса);
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;

		КонецЦикла;

		Для Каждого ТекДанныеПроцесса Из ПроцессыДляСнятиеСкриншотов Цикл
			ТекДанныеПроцесса.Вставить("ЭтоДополнительныйПроцессДляСнятиеСкриншотов", Истина);
		КонецЦикла;

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

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

&НаКлиенте

Процедура ОпределитьСвойстваПроцессаИСделатьСкриншотЕслиНеобходимо()
	ИдДанныеСпискаПроцессов = ИдДанныеСпискаПроцессов + 1;
	Если ИдДанныеСпискаПроцессов > (ДанныеСпискаПроцессов.Количество() - 1) Тогда
		Если НЕ ЗапрещеныСинхронныеВызовы Тогда
			Если ЗакрытьМодальныйДиалогИСнятьСкриншот() Тогда
				Возврат;
			КонецЕсли;
		КонецЕсли;

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

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

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

		ПерейтиКВыполнениюСледующегоСценария();

		Возврат;

	КонецЕсли;

	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("ДанныеПроцесса", ДанныеСпискаПроцессов[ИдДанныеСпискаПроцессов]);

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

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

&НаКлиенте

[Assistant] Функция ЗакрытьМодальныйДиалогИСнятьСкриншот()


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

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

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

	НадоЗапускатьПриложение = Ложь;
	Если Не ЗначениеЗаполнено(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) Тогда
		// Значит не указано имя ПК для запуска. Это равносильно указанию localhost
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли НРег(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) = "localhost" Тогда
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли НРег(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) = "127.0.0.1" Тогда
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиент"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиентАвтономный"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильноеПриложение" Тогда
		// браузер или мобильный клиент мы можем спокойно запускать
		НадоЗапускатьПриложение = Истина;
	КонецЕсли;

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

	ПроисходилЗапускTescClient = Истина;

	ДопПараметрыЗапуска = Новый Структура;
	Если ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web" Тогда
		СтрокаЗапуска = ПолучитьСтрокуЗапускаWebКлиент(ДанныеЗапускаКлиентаТестирования);
	ИначеЕсли ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиент"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиентАвтономный"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильноеПриложение" Тогда
		СтрокаЗапуска = ПолучитьСтрокуЗапускаМобильныйКлиент(ДанныеЗапускаКлиентаТестирования);
	Иначе
		Если Найти(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе, "=") = 0 И Найти(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе, ";") = 0 Тогда
			Если ФайлСуществуетКомандаСистемы(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе) Тогда
				ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе = "File=""" + ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе + """;";
			КонецЕсли;
		КонецЕсли;
		СтрокаЗапуска = ПолучитьСтрокуЗапускаDesktopПриложение(ДанныеЗапускаКлиентаТестирования, ДопПараметрыЗапуска);
	КонецЕсли;

	ТекстСообщения = Локализовать("СтрокаЗапуска=%1");
	ТекстСообщения = СтрЗаменить(ТекстСообщения, "%1", СтрокаЗапуска);
	Отладка(Локализовать(ТекстСообщения));

	Если ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web" Тогда

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

		Если  Объект.ИспользоватьБраузерПлюсWebSocket И НЕ ПустаяСтрока(Объект.КомандаЗапускаБраузера)
			И Объект.ИспользоватьКомпонентуVanessaExt Тогда

			КоличествоПопыток = 3;
			БылаОшибка = Ложь;
			ТекстОшибки = "";
			Для СчетчикПопыток = 1 По КоличествоПопыток Цикл
				ТекстОшибки = "";
				БылаОшибка = Ложь;

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

					Прервать;
				Исключение
					ТекстОшибки = ОписаниеОшибки();
					БылаОшибка = Истина;
					sleep(1);
				КонецПопытки;

			КонецЦикла;

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

			ТекстJSON = HTTPОтвет.ПолучитьТелоКакСтроку();
			ЧтениеJSON = Новый ЧтениеJSON;
			ЧтениеJSON.УстановитьСтроку(ТекстJSON);
    // TODO: допиши оставшуюся часть

[Assistant]
Процедура ЗапуститьКлиентаТестирования(ДанныеЗапускаКлиентаТестирования, ДопПараметр = "")
	#Если НЕ ВебКлиент Тогда

	НадоЗапускатьПриложение = Ложь;
	Если Не ЗначениеЗаполнено(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) Тогда
		// Значит не указано имя ПК для запуска. Это равносильно указанию localhost
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли НРег(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) = "localhost" Тогда
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли НРег(ДанныеЗапускаКлиентаТестирования.ИмяКомпьютера) = "127.0.0.1" Тогда
		НадоЗапускатьПриложение = Истина;
	ИначеЕсли ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиент"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиентАвтономный"
		Или ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильноеПриложение" Тогда
		// браузер или мобильный клиент мы можем спокойно запускать
		НадоЗапускатьПриложение = Истина;
	КонецЕсли;

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

	ПроисходилЗапускTescClient = Истина;

	ДопПараметрыЗапуска = Новый Структура;
	Если ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web" Тогда
		СтрокаЗапуска = ПолучитьСтрокуЗапускаWebКлиент(ДанныеЗапускаКлиентаТестирования);
	ИначеЕсли ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиент"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиентАвтономный"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильноеПриложение" Тогда
		СтрокаЗапуска = ПолучитьСтрокуЗапускаМобильныйКлиент(ДанныеЗапускаКлиентаТестирования);
	Иначе
		Если Найти(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе, "=") = 0 И Найти(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе, ";") = 0 Тогда
			Если ФайлСуществуетКомандаСистемы(ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе) Тогда
				ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе = "File=""" + ДанныеЗапускаКлиентаТестирования.ПутьКИнфобазе + """;";
			КонецЕсли;
		КонецЕсли;
		СтрокаЗапуска = ПолучитьСтрокуЗапускаDesktopПриложение(ДанныеЗапускаКлиентаТестирования, ДопПараметрыЗапуска);
	КонецЕсли;

	ТекстСообщения = Локализовать("СтрокаЗапуска=%1");
	ТекстСообщения = СтрЗаменить(ТекстСообщения, "%1", СтрокаЗапуска);
	Отладка(Локализовать(ТекстСообщения));

	Если ДанныеЗапускаКлиентаТестирования.ТипКлиента = "Web" Тогда

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

		Если  Объект.ИспользоватьБраузерПлюсWebSocket И НЕ ПустаяСтрока(Объект.КомандаЗапускаБраузера)
			И Объект.ИспользоватьКомпонентуVanessaExt Тогда

			КоличествоПопыток = 3;
			БылаОшибка = Ложь;
			ТекстОшибки = "";
			Для СчетчикПопыток = 1 По КоличествоПопыток Цикл
				ТекстОшибки = "";
				БылаОшибка = Ложь;

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

					Прервать;
				Исключение
					ТекстОшибки = ОписаниеОшибки();
					БылаОшибка = Истина;
					sleep(1);
				КонецПопытки;

			КонецЦикла;

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

			ТекстJSON = HTTPОтвет.ПолучитьТелоКакСтроку();
			ЧтениеJSON = Новый ЧтениеJSON;
			ЧтениеJSON.УстановитьСтроку(ТекстJSON);
			ДанныеJSON = ПрочитатьJSON(ЧтениеJSON);
			АдресВебСокет = ДанныеJSON.webSocketDebuggerUrl;
			ИдентификаторФрейма = ДанныеJSON.id;
			ИдентификаторФреймаТекущегоWebКлиента = ИдентификаторФрейма;
			РезультатПодключения = ВнешняяКомпонентаДляСкриншотов.ОткрытьВебСокет(АдресВебСокет);
			Если Не ПустаяСтрока(РезультатПодключения) Тогда
				ВызватьИсключение ПодставитьПараметрыВСтроку(
					Локализовать("Ошибка подключения WebSocket.")
				);
			КонецЕсли;
		Иначе
			Если НЕ ПустаяСтрока(Объект.КомандаЗапускаБраузера) Тогда
				Если Найти(Объект.КомандаЗапускаБраузера, "TestClientUrl") > 0 Тогда
					СтрокаЗапуска = СтрЗаменить(Объект.КомандаЗапускаБраузера, "TestClientUrl", СтрокаЗапуска);
				Иначе
					СтрокаЗапуска = Объект.КомандаЗапускаБраузера + " " + СтрокаЗапуска;
				КонецЕсли;
			КонецЕсли;

			Если ЗапрещеныСинхронныеВызовы Тогда
				СтрокаКоманды = "start """" """ + СтрокаЗапуска + """";
				ЗаписатьЛогВЖРИнформация("ЗапуститьКлиентаТестирования", СтрокаКоманды);
				ВыполнитьКомандуОСБезПоказаЧерногоОкна(СтрокаКоманды, 0);
			Иначе
				ЗаписатьЛогВЖРИнформация("ЗапуститьКлиентаТестирования", СтрокаЗапуска);
				ЗапуститьПриложение(СтрокаЗапуска);
			КонецЕсли;
		КонецЕсли;
	ИначеЕсли ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиент"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильныйКлиентАвтономный"
		ИЛИ ДанныеЗапускаКлиентаТестирования.ТипКлиента = "МобильноеПриложение" Тогда
		Если ВозможноЗапуститьМобильныйКлиент() Тогда
			ЗаписатьЛогВЖРИнформация("ЗапуститьКлиентаТестирования", СтрокаЗапуска);
			СтартМобильногоКлиентаТестирования(СтрокаЗапуска, ДанныеЗапускаКлиентаТестирования.ТипКлиента, Объект.ТаймаутЗапуска1С);
		Иначе
			ВызватьИсключение ПодставитьПараметрыВСтроку(
					Локализовать("Не обнаружено подключенное устройство.")
				);
		КонецЕсли;
	ИначеЕсли Не ЗначениеЗаполнено(ДанныеЗапускаКлиентаТестирования.ТипКлиента) Или
		Найти(НРег(ДанныеЗапускаКлиентаТестирования.ТипКлиента), "тонкий") > 0 Или
		ЭтоLinux Тогда

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

		ЗапуститьСеанс1СЧерез1cv8(ДанныеЗапускаКлиентаТестирования, СтрокаЗапуска);
	Иначе
		ЗапуститьСеанс1СЧерез1cv8(ДанныеЗапускаКлиентаТестирования, СтрокаЗапуска);
	КонецЕсли;

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

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

&НаКлиенте
// Возвращает строку обернутую кавычками.

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

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

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

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


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

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

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

    Чтение = Новый ЧтениеXML;
    Чтение.УстановитьСтроку(
                "<Model xmlns=""http://v8.1c.ru/8.1/xdto"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""Model"">
                |<package targetNamespace=""sample-my-package"">
                |<valueType name=""testtypes"" base=""xs:string"">
                |<pattern>" + СтрЗаменить(СтрЗаменить(Фасет, """", """), Символы.ПС, "~ПереводСтроки~") + "</pattern>
                |</valueType>
                |<objectType name=""TestObj"">
                |<property xmlns:d4p1=""sample-my-package"" name=""TestItem"" type=""d4p1:testtypes""/>
                |</objectType>
                |</package>
                |</Model>");

	#Если ВебКлиент Тогда
    Модель = Неопределено;
	#Иначе
	Попытка
	    Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);
	Исключение
		СообщениеОбОшибке = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ЗаписатьЛогВЖРОшибкаСервер("VanessaAutomation.ПроверитьСтрокуRegExpLinux",
			"<" + Строка + ">" + Символы.ПС + "<" + Фасет + ">" + Символы.ПС + СообщениеОбОшибке);
		ВызватьИсключение СообщениеОбОшибке;
	КонецПопытки;
	#КонецЕсли
    МояФабрикаXDTO = Новый ФабрикаXDTO(Модель);
    Пакет = МояФабрикаXDTO.Пакеты.Получить("sample-my-package");
    Тест = МояФабрикаXDTO.Создать(Пакет.Получить("TestObj"));

    Попытка
        Тест.TestItem = СтрЗаменить(Строка, Символы.ПС, "~ПереводСтроки~");
        Возврат Истина;
    Исключение
        Возврат Ложь;
	КонецПопытки;

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

&НаКлиенте

Процедура ПроверитьФлагОстановкаПриВозникновенииОшибки()
	Если Объект.ОстановкаПриВозникновенииОшибки Тогда
		СообщитьПользователю(Локализовать("Установлен флаг <Остановка при возникновении ошибки>. Выполнение следующих сценариев/шагов отменено."));
		ПрекратитьВыполнениеВсехСценариев = Истина;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

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

&НаКлиенте

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

	Если ИмяРеквизита = ОбъектКонтекст.АктивнаяТаблицаTestClient.ИмяТаблицы Тогда
		Возврат ОбъектКонтекст.АктивнаяТаблицаTestClient.Значение;
	КонецЕсли;

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

&НаКлиенте

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

	Если МодульСообщенийПользователю = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;

	Возврат МодульСообщенийПользователю.ДанныеПереводаСообщений(Объект.ВерсияПоставки, ЭтаФорма);
КонецФункции

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

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

		ДопПараметры.ВозможнаОптимизацияРаботыСФайлами = Истина;
		ТекстовыйДокумент = Новый ТекстовыйДокумент;

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

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

&НаСервере

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

	КешВерсияОбработки = ПолучитьВерсиюОбработкиСервер();
	ДопПараметры.Вставить("КешВерсияОбработки", КешВерсияОбработки);

	ЕстьКонстантаВКонфигурацииПутьКVA = ЕстьКонстантаВКонфигурацииСервер("ПутьКVanessaAutomation");
	ДопПараметры.Вставить("ЕстьКонстантаВКонфигурацииПутьКVA", ЕстьКонстантаВКонфигурацииПутьКVA);

	ВосстановитьВсеНастройкиСервер(ДопПараметры);

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

	ВосстановитьНастройкиИзХранилищаКеш();

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

	ПроверкаВозможностиОптимизацииРаботыСФайлами(ДопПараметры);

	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	ОбъектСервер.ТекстСообщенийПользователю = ДопПараметры.ТекстСообщенийПользователю;

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

		Если НадоУстановитьПустойПуть Тогда
			ОбъектСервер.КаталогФич = "";
		КонецЕсли;
	КонецЕсли;

	ЗначениеВРеквизитФормы(ОбъектСервер, "Объект");

	Если Объект.ОтображатьЗакладкиСверху Тогда
		Элементы.ФункциональностьЗакладки.ОтображениеСтраниц = ОтображениеСтраницФормы.ЗакладкиСверху;
	КонецЕсли;

	ДоступностьКнопокОтката = Ложь;

	Если ДопПараметры.РежимСовместимостиБольшеИлиРавен837 Тогда
		РасширениеКонфигурации = РасширениеКонфигурации("ОткатИзмененийДанных");
		Если РасширениеКонфигурации <> Неопределено И СравнитьВерсии(РасширениеКонфигурации.Версия, "1.0.0.4") >= 0 Тогда
			ДоступностьКнопокОтката = Истина;
		КонецЕсли;
	КонецЕсли;

	Элементы.ВыгрузитьВСистемуОтката.Доступность = ДоступностьКнопокОтката;
	Элементы.ЗагрузитьИзСистемыОтката.Доступность = ДоступностьКнопокОтката;

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

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

Функция РасширениеКонфигурации(ИмяРасширения)

	Если НЕ ПравоДоступа("АдминистрированиеРасширенийКонфигурации", Метаданные) Тогда
		 Возврат Неопределено;
	КонецЕсли;

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

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

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

&НаКлиенте

Процедура ОбновитьВидимостьЭлементовПослеЗагрузкиНастроек()
	УстановитьУсловноеОформление();
КонецПроцедуры

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

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

	Если ВНРегистр Тогда
		УниверсальноеПолноеИмя = НРег(УниверсальноеПолноеИмя);
	КонецЕсли;

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

&НаКлиенте

Функция ЭтоТонкийКлиент()
	Значение = Истина;
	#Если ТолстыйКлиентУправляемоеПриложение Тогда
		Значение = Ложь;
	#КонецЕсли

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

&НаКлиенте

Функция ЭтоМенеджерТестирования()

	Попытка
		Значение = Тип("ТестируемоеПриложение") <> Неопределено;
	Исключение
		Значение = Ложь;
	КонецПопытки;

	Возврат Значение;

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

&НаКлиенте

[Assistant] Функция ПроверитьСтрокуRegExpLinux(Знач Строка, Знач Фасет)


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

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

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

	Если ЭтоLinux Тогда
		Возврат "";
	КонецЕсли;

	ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
	ВыполнитьКомандуОСБезПоказаЧерногоОкна("echo " + ИмяПараметра + " > """ + ИмяВременногоФайла + """");

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

	Если ЗначениеСтроки = Неопределено Тогда
		ЗначениеСтроки = "";
	КонецЕсли;

	Возврат СокрЛП(ЗначениеСтроки);

	#КонецЕсли
КонецФункции

&НаКлиенте

Процедура ЗаменитьUIDФайлеОбработки(ИмяФайла, ЧастьСтроиПоиска, UID)

	СтрокаПоиска = Неопределено;

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

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

		Поз = Найти(Стр, ЧастьСтроиПоиска);
		Если Поз > 0 Тогда
			СтрокаПоиска = СокрЛП(Стр);
		КонецЕсли;
	КонецЦикла;

	Текст.Закрыть();

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

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

	ТекстФайла = Текст.Прочитать();

	СтрокаЗамены = ЧастьСтроиПоиска + """%1"">";
	СтрокаЗамены = СтрЗаменить(СтрокаЗамены, "%1", UID);

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

	ТекстФайла = СтрЗаменить(ТекстФайла, СтрокаПоиска, СтрокаЗамены);

	Текст.Закрыть();

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

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

&НаКлиенте

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

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

&НаСервере

Процедура ВыделитьСтрокиСценарияКакКодВстроенногоЯзыкаНаСервере(Знач НомерНачальнойСтроки, Знач НомерКонечнойСтроки)

	СимволыНачалаВыделения = "|' ";
	СимволыКонцаВыделения  = " '|";

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

	НеобрабатываемыеСтроки = Новый Массив;

	Для Каждого СвойстваСтроки Из СвойстваОтдельныхСтрок Цикл

		НеобходимоВыделение = Лев(СвойстваСтроки.СтрокаСокрЛП, СтрДлина(СимволыНачалаВыделения)) <> СимволыНачалаВыделения
								Или Прав(СвойстваСтроки.СтрокаСокрЛП, СтрДлина(СимволыКонцаВыделения)) <> СимволыКонцаВыделения;

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

		Если Не СвойстваСтроки.СтрокаПуста Тогда

			ДлинаДоЭкранирования = СтрДлина(СвойстваСтроки.СтрокаУсредненная);
			СвойстваСтроки.СтрокаУсредненная = ЭкранироватьСпецСимволыДляЗначенияШага(СвойстваСтроки.СтрокаУсредненная);
			ДлинаПолеЭкранирования = СтрДлина(СвойстваСтроки.СтрокаУсредненная);
			РазницаДлинДоИПослеЭкранирования = ДлинаПолеЭкранирования - ДлинаДоЭкранирования;

			Если СвойстваСтроки.ДлинаСокрПрав = СвойстваГруппыВыделенныхСтрок.МаксимальнаяДлинаСтрокиСокрПрав
				И РазницаДлинДоИПослеЭкранирования > 0 Тогда

				СвойстваГруппыВыделенныхСтрок.МаксимальнаяДлинаСтрокиСокрПрав = СвойстваГруппыВыделенныхСтрок.МаксимальнаяДлинаСтрокиСокрПрав
																				+ РазницаДлинДоИПослеЭкранирования;
			КонецЕсли;

			СвойстваСтроки.ДлинаСокрПрав = СвойстваСтроки.ДлинаСокрПрав + РазницаДлинДоИПослеЭкранирования;

		КонецЕсли;

	КонецЦикла;

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

	Для Каждого СвойстваСтроки Из СвойстваОтдельныхСтрок Цикл

		НехваткаСимволовДоМаксимальнойДлины = 0;

		Если СвойстваСтроки.СтрокаПуста Тогда
			НехваткаСимволовДоМаксимальнойДлины = СвойстваГруппыВыделенныхСтрок.МаксимальнаяДлинаСтрокиСокрПрав
													- СвойстваГруппыВыделенныхСтрок.МинимальноеКоличествоПустыхСимволовСлева;
		Иначе
			НехваткаСимволовДоМаксимальнойДлины = СвойстваГруппыВыделенныхСтрок.МаксимальнаяДлинаСтрокиСокрПрав
													- СвойстваСтроки.ДлинаСокрПрав;
		КонецЕсли;

		// Для выравнивания всегда используем пробелы, даже если отступы сформированы табуляцией, так как строки все равно будут
		// оборачиваться в СимволыНачалаВыделения и СимволыКонцаВыделения, а пробелы гарантируют более стаблильное выравнивание.
		ПробелыВыравнивания = "";
		Для Счетчик = 1 По НехваткаСимволовДоМаксимальнойДлины Цикл
			ПробелыВыравнивания = ПробелыВыравнивания + " ";
		КонецЦикла;

		НоваяСтрока = СвойстваСтроки.ПустыеСимволыУсреденннойСтрокиСлева
						+ СимволыНачалаВыделения
						+ СвойстваСтроки.СтрокаУсредненная
						+ ПробелыВыравнивания
						+ СимволыКонцаВыделения;
		ТекстКакДокумент.ЗаменитьСтроку(СвойстваСтроки.НомерСтроки, НоваяСтрока);

	КонецЦикла;

	Объект.СгенерированныйСценарий = ТекстКакДокумент.ПолучитьТекст();

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

&НаСервере

[Assistant] Функция ЗначениеСистемногоПараметра(ИмяПараметра)


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

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

Функция ИмяФункции(ДанныеРеестра, ИмяФайла)

	Если _СтрНайти(ДанныеРеестра, "<component") = 0 Тогда // Файл пустой
		ДанныеРеестра = _СтрШаблон("<?xml version=""1.0"" encoding=""UTF-8""?>
						  |<registry xmlns=""http://v8.1c.ru/8.2/addin/registry"">
						  |	<component path=""%1"" type=""native""/>
						  |</registry>", ИмяФайла);
	ИначеЕсли _СтрНайти(ДанныеРеестра, _СтрШаблон("path=""%1""", ИмяФайла)) <> 0 Тогда // Компонента уже зарегистрирована
		Возврат Ложь;
	Иначе // Добавляем компоненту
		Запись = _СтрШаблон("	<component path=""%1"" type=""native""/>", ИмяФайла);
		ДанныеРеестра = СтрЗаменить(ДанныеРеестра, "</registry>", Запись + Символы.ПС + "</registry>");
	КонецЕсли;

	Возврат Истина;

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

&НаКлиенте

Процедура ЗаписатьФайлRegistry(ПараметрыТихойУстановки)

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

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

&НаКлиенте

Функция ОписаниеПлатформы()

	СистемнаяИнформация = Новый СистемнаяИнформация;

	ОперационнаяСистема = Неопределено;
	Архитектура = Неопределено;

	Linux = "Linux";
	Windows = "Windows";
	MacOS = "MacOS";

	x86 = "i386";
	x64 = "x86_64";

	ТипКлиентскойПлатформы = СистемнаяИнформация.ТипПлатформы;

	Если ТипКлиентскойПлатформы = ТипПлатформы.Linux_x86 Тогда
		ОперационнаяСистема = Linux;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Linux_x86_64 Тогда
		ОперационнаяСистема = Linux;
		Архитектура = x64;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Windows_x86 Тогда
		ОперационнаяСистема = Windows;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.Windows_x86_64 Тогда
		ОперационнаяСистема = Windows;
		Архитектура = x64;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.MacOS_x86 Тогда
		ОперационнаяСистема = MacOS;
		Архитектура = x86;
	ИначеЕсли ТипКлиентскойПлатформы = ТипПлатформы.MacOS_x86_64 Тогда
		ОперационнаяСистема = MacOS;
		Архитектура = x64;
	Иначе
		ВызватьИсключение "Неподдерживаемый тип платформы";
	КонецЕсли;

	Возврат Новый Структура("ОперационнаяСистема, Архитектура", ОперационнаяСистема, Архитектура);

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

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

Функция ФайлКомпоненты(Знач АдресХранилища, Знач ОперационнаяСистема, Знач Архитектура)

	Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
	ЧтениеАрхива = Новый ЧтениеZipФайла();
	ЧтениеАрхива.Открыть(Данные.ОткрытьПотокДляЧтения());

	ИмяФайлаКомпоненты = ИмяФайлаКомпоненты(ЧтениеАрхива, ОперационнаяСистема, Архитектура);

	Если ИмяФайлаКомпоненты = Неопределено Тогда
		ВызватьИсключение "Компонента не поддерживает клиентское окружение";
	КонецЕсли;

	Данные = ДвоичныеДанныеЭлемента(ЧтениеАрхива, ИмяФайлаКомпоненты);

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

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

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

Функция ИмяФайлаКомпоненты(ЧтениеАрхива, ОперационнаяСистема, Архитектура)

	Данные = ДвоичныеДанныеЭлемента(ЧтениеАрхива, "MANIFEST.XML");

	Если Данные = Неопределено Тогда
		ВызватьИсключение "Архив компоненты не содержит манифеста";
	КонецЕсли;

	ЧтениеXML = Новый ЧтениеXML();
	ЧтениеXML.ОткрытьПоток(Данные.ОткрытьПотокДляЧтения());

	ИмяФайлаКомпоненты = Неопределено;

	Пока ЧтениеXML.Прочитать() Цикл

		Если ЭтоПодходящийУзел(ЧтениеXML, ОперационнаяСистема, Архитектура) Тогда
			ИмяФайлаКомпоненты = ЧтениеXML.ЗначениеАтрибута("path");
			Прервать;
		КонецЕсли;

	КонецЦикла;

	ЧтениеXML.Закрыть();

	Возврат ИмяФайлаКомпоненты;

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

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

Функция ЭтоПодходящийУзел(ЧтениеXML, ОперационнаяСистема, Архитектура)

	Если ЧтениеXML.ТипУзла <> ТипУзлаXML.НачалоЭлемента ИЛИ НРег(ЧтениеXML.Имя) <> "component" Тогда
		Возврат Ложь;
	КонецЕсли;

	ОперационнаяСистемаУзла = ЧтениеXML.ЗначениеАтрибута("os");
	АрхитектураУзла = ЧтениеXML.ЗначениеАтрибута("arch");

	Возврат ОперационнаяСистема = ОперационнаяСистемаУзла И Архитектура = АрхитектураУзла;

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

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

Функция ДвоичныеДанныеЭлемента(ЧтениеАрхива, ИмяФайла)

	ЭлементФайла = Неопределено;

	Для Каждого Элемент Из ЧтениеАрхива.Элементы Цикл
		Если ВРег(Элемент.ПолноеИмя) = ВРег(ИмяФайла) Тогда
			ЭлементФайла = Элемент;
		КонецЕсли;
	КонецЦикла;

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

	ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
	ЧтениеАрхива.Извлечь(ЭлементФайла, ИмяВременногоФайла, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);

	Данные = Новый ДвоичныеДанные(ОбъединитьПути(ИмяВременногоФайла, , ,  , , ЭлементФайла.Имя));
	УдалитьФайлы(ИмяВременногоФайла);

	Возврат Данные;

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

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

&НаКлиенте

Функция ЭтоЗапускИзКоманднойСтроки()

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

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

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

&НаКлиенте

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

&НаКлиенте

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

	Если СтрокаСценария.ПроизвольныеЗначения = Неопределено Тогда
		СтрокаСценария.ПроизвольныеЗначения = Новый Структура;
	КонецЕсли;

	Если НЕ СтрокаСценария.ПроизвольныеЗначения.Свойство("МассивСкриншотов") Тогда
		СтрокаСценария.ПроизвольныеЗначения.Вставить("МассивСкриншотов", Новый Массив);
	КонецЕсли;

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

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

&НаСервере

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

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

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

&НаКлиенте

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

&НаКлиенте

Функция ОтступПоЧислуПробелов(Кол)
	Стр = "";
	Для Сч = 1 По Кол Цикл
		Стр = Стр + "  ";
	КонецЦикла;
	Возврат Стр;
КонецФункции

&НаКлиенте

[Assistant] Функция ЗаписатьВРеестр(ДанныеРеестра, ИмяФайла)