Содержит свойства, специфичные для поля вида ПолеФорматированногоДокумента.
Полное описание, параметры и ограничения
Расширение тестируемого поля формы для форматированного документа (Tested form field extension for a formatted document)
Расширение тестируемого поля формы для форматированного документа (Tested form field extension for a formatted document)
Доступен, начиная с версии 8.3.8.
Методы:
ВвестиHTMLДокумента (InputDocumentHTML)
ЗаписатьСодержимоеВФайл (WriteContentToFile)
НажатьНаГиперссылкуВФорматированномДокументе (ClickFormattedDocumentHyperlink)
ПолучитьHTMLДокумента (GetDocumentHTML)
УстановитьHTMLДокумента (SetDocumentHTML)
Описание:
Содержит свойства, специфичные для поля вида ПолеФорматированногоДокумента.
Доступность:
Тонкий клиент, толстый клиент.
Использование в версии:
Доступен, начиная с версии 8.3.8.
Описание изменено в версии 8.3.25.
Методическая информация
Практические примеры
Проверить форматированный счет и восстановить сохраненный native HTML
Две собственные клиентские программы и настоящий серверный HTML consumer показывают отличие источника, native результата и будущего GUI опыта.
Где и как запускать
Платформа8.5.1.1343; полный модуль собственной общей управляемой Manager-формы; WindowsThickManaged /TestManager, readonly server passport и scalar RPC. Runtime не выполнялся.
Подготовка
Это будущий ручной опыт только в собственной Windows VM. Новая File CF УчебныйHTMLТестСчет85: C:\1c-labs\OwnTestedHTMLInvoice85_6715c6dc-3a27-43c2-a31f-34c44d4c77af\IB; точная платформа8.5.1.1343, основной режим УправляемоеПриложение, совместимость НеИспользовать. UUID каталога — метка стенда, не UUID ИБ. Стенд/CF/процессы/порты здесь не создавались.
С нуля создайте ровно три общие управляемые формы ИсточникHTML85, МенеджерHTML85, МенеджерФормат85; один общий модуль УчебныйHTMLСтенд85 и свою роль HTML85ПолныеПрава. Прикладных объектов/данных/расширений нет. В роли разрешите Администрирование для native GetUsers и открытие своих общих форм. Один реальный пользователь HTML85Ученик с этой ролью; никакого чужого аккаунта.
COMMON из supportingModules: общий модуль УчебныйHTMLСтенд85, СерверДа, ВызовСервераДа, ГлобальныйНет, ПривилегированныйНет, оба КлиентНет, ВнешнееСоединениеНет, ПовторноеИспользованиеВозвращаемыхЗначенийНеИспользовать. Из клиентов передаются только строки/число/Булево; HTMLReader/DOM/Formatted native объекты остаются в разрешенном контексте.
ИсточникHTML85: реквизиты Метка85/Пользователь85 Строка36, HTML85 Строка неограниченная, Формат85 ФорматированныйДокумент, Готов85/Стоп85 Булево, Нажатий85 Число5.0, ИтогСсылки85/Состояние85 Строка неограниченная. HTMLПоле85/ФорматПоле85 руками не создавайте: код Add→actual ПолеФормы→Вид→ПутьКДанным делает это на сервере.
В Source разместите только readonly обычные поля Метка85, Пользователь85, Состояние85, Нажатий85, ИтогСсылки85, одноименные DataPath. Для Нажатий85 задайте Формат="ЧДЦ=0;ЧГ=0;ЧН=0". Событие ПриСозданииНаСервере назначьте одноименной процедуре. Полный SOURCE поддерживает ПриНажатии3 и ДокументСформирован1 через native SetAction. Не вызывайте эти обработчики вручную.
У обеих manager-форм реквизиты Метка85 Строка36/поле, Согласие85 Булево/флажок и Итог85 Строка неограниченная/readonly поле. Событие ПриОткрытии→ПриОткрытии(Отказ). Две команды Начать85 и Шаг85, Действие — одноименные процедуры с одним параметром Команда; две кнопки с соответствующим ИмяКоманды. В МенеджерHTML85 вставьте MAIN первого урока, в МенеджерФормат85 — MAIN второго. Ни один модуль не должен быть подставлен в неизвестную форму.
Модуль управляемого приложения — полный APPLICATION. Назначьте ПриНачалеРаботыСистемы. Source/manager открываются только по своему /C. В списке баз у своей регистрации явно выберите клиент Толстый клиент; /RunModeManagedApplication учитывает эту настройку. Сам #Если ТолстыйКлиентУправляемоеПриложение откажет при другом клиенте; один ключ запуска не доказывает actual client.
Установленная справка1cv8_ru.hbk zif2_testclient подтверждает /TestClient [-TPort<Номер TCP-порта>] для толстого/тонкого; zif2_TestManager — /TestManager также для обоих. Человек предварительно проверяет, что127.0.0.1:15387 свободен и используется только своими двумя приложениями. Никакой automated launch/port/network check в этом уроке не выполняется.
Первый ручной запуск: "C:\Program Files\1cv8\8.5.1.1343\bin\1cv8.exe" ENTERPRISE /F "C:\1c-labs\OwnTestedHTMLInvoice85_6715c6dc-3a27-43c2-a31f-34c44d4c77af\IB" /N "HTML85Ученик" /RunModeManagedApplication /TestClient -TPort15387 /C "Source85". Не добавляйте UILogRecorder/файлы/пароли/производственные пути. Закройте Конфигуратор перед опытом.
Второй ручной запуск того же собственного стенда и пользователя: тот же executable/ENTERPRISE/F/N/RunModeManagedApplication, но /TestManager /C "ManagerHTML85" для первого урока или /C "ManagerRich85" для второго. Source должен быть единственной открытой формой TestClient; настоящий UUID из его Метка85 перенесите в Manager. Каждый урок начинайте двумя свежими собственными запусками, не повторно после STOP.
Данные в памяти: BOOK2×250=500; PAPER5×50=250; TEA3×100=300. Количество10/итог1050. Единственное изменение PAPER50→70 дает350/1150; возврат PAPER50 восстанавливает1050. У каждой строки читаются actual код/количество/цена/сумма из native HTML, не из запроса, literal или подготовленного golden.
GetDocumentHTML имеет два обязательных OUT-параметра HTML:Строка и Вложения:Соответствие, не return. У серверного FormattedDocument.SetHTML вложения обязательны и Структура; у tested Input optional Соответствие. У tested Formatted.SetDocumentHTML тип optional вложений не объявлен: в коде только один обязательный HTML, никаких догадок.
HTML link — лишь внутренний #own-verify-actualUUID. OnClick данные.Href только scalar; COM-методы браузера не вызываются. Допускаются exact fragment или exact about:blank+fragment, иное форматирование URL честно отказывает. Standard=False не отменяет действие по native; это НЕ sandbox/security/url blocker.
Дождитесь собственной Source-готовности. Начать85→Шаг85 три раза. Каждый следующий шаг перечитывает полный own state; после ошибки текущий Manager/Source не сбрасываются, restore/retry/закрытие чужих окон/удаление данных отсутствуют. Если форматирование преобразовало HTML так, что полный typed snapshot не читается, зафиксируйте STOP, не подставляйте ожидаемые ячейки.
Здесь написанный урок и статические проверки installed contracts. Реальная1С/compiled CF/GUI/DB/порт/network не выполнялись. Semantic readback не доказывает byte-identical HTML, pixels/renderer, атомарность UI или гарантированное время native событий.
Перем Тест85;
Перем Этап85;
Перем Стоп85;
Перем Пользователь85;
Перем БазаHTML85;
Перем БазаСнимок85;
Перем ИзмененныйСнимок85;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Этап85 = 0;
Стоп85 = Ложь;
Согласие85 = Ложь;
Метка85 = "";
Итог85 = "Перенесите настоящий UUID своей Source-формы. Сначала отдельное согласие, затем Начать85";
КонецПроцедуры
&НаКлиенте
Функция Поле85(Форма, Имя)
Поле = Форма.ПолучитьОбъект(Тип("ТестируемоеПолеФормы"), , Имя, 3);
Если ТипЗнч(Поле) <> Тип("ТестируемоеПолеФормы") Или Поле.Имя <> Имя
Или Не Поле.ТекущаяВидимость() Или Не Поле.ТекущаяДоступность() Тогда
ВызватьИсключение "Не получено точное настоящее собственное доступное поле";
КонецЕсли;
Возврат Поле;
КонецФункции
&НаКлиенте
Функция Контроль85(Форма, Имя)
Возврат Поле85(Форма, Имя).ПолучитьПредставлениеДанных();
КонецФункции
&НаКлиенте
Функция СвояФорма85()
Если Стоп85 Или Тест85 = Неопределено Или Пользователь85 <> УчебныйHTMLСтенд85.Паспорт85() Тогда
ВызватьИсключение "Предыдущая ошибка или чужой пользователь/стенд";
КонецЕсли;
Формы = Тест85.НайтиОбъекты(Тип("ТестируемаяФорма"), , , 3);
Если ТипЗнч(Формы) <> Тип("ФиксированныйМассив") Или Формы.Количество() <> 1 Тогда
ВызватьИсключение "В TestClient должна быть только одна собственная Source-форма";
КонецЕсли;
Форма = Формы[0];
Если ТипЗнч(Форма) <> Тип("ТестируемаяФорма") Или Форма.ТекстЗаголовка <> "OwnHTML85 " + Метка85
Или Контроль85(Форма, "Метка85") <> Метка85 Или Контроль85(Форма, "Пользователь85") <> Пользователь85
Или Контроль85(Форма, "Состояние85") <> "READY" Тогда
ВызватьИсключение "Не совпали настоящий UUID, пользователь, заголовок или готовность Source";
КонецЕсли;
Возврат Форма;
КонецФункции
&НаКлиенте
Функция ДокументПоле85(Форма)
Поле = Поле85(Форма, "ФорматПоле85");
Если Поле.Вид <> ВидПоляФормы.ПолеФорматированногоДокумента Или Поле.ТекущееТолькоПросмотр() Тогда
ВызватьИсключение "Не тот actual native kind или настоящее поле readonly";
КонецЕсли;
Возврат Поле;
КонецФункции
&НаКлиенте
Функция ПрочитатьПоле85(Поле, ЦенаБумаги)
HTML = "";
Вложения = Новый Соответствие;
Поле.ПолучитьHTMLДокумента(HTML, Вложения);
Если ТипЗнч(HTML) <> Тип("Строка") Или HTML = "" Или ТипЗнч(Вложения) <> Тип("Соответствие") Или Вложения.Количество() <> 0 Тогда
ВызватьИсключение "Не получены оба настоящих OUT-параметра HTML/Соответствие без вложений";
КонецЕсли;
Снимок = УчебныйHTMLСтенд85.Снимок85(HTML, Метка85, ЦенаБумаги);
Возврат Новый ФиксированнаяСтруктура("HTML,Снимок", HTML, Снимок);
КонецФункции
&НаКлиенте
Процедура Начать85(Команда)
Если Стоп85 Или Этап85 <> 0 Или Не Согласие85 Тогда
Стоп85 = Истина;
ВызватьИсключение "Требуется одно явное согласие на свой TestClient в свежем экземпляре Manager";
КонецЕсли;
Согласие85 = Ложь;
Попытка
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Пользователь85 = УчебныйHTMLСтенд85.Паспорт85();
Если СтрДлина(Метка85) <> 36 Или Строка(Новый УникальныйИдентификатор(Метка85)) <> Метка85 Тогда
ВызватьИсключение "Нужно перенести реальный canonical UUID Source, не генерировать новый";
КонецЕсли;
Тест85 = Новый ТестируемоеПриложение("127.0.0.1", 15387);
Тест85.УстановитьСоединение();
Форма = СвояФорма85();
Если Контроль85(Форма, "Нажатий85") <> "0" Или Контроль85(Форма, "ИтогСсылки85") <> "" Тогда
ВызватьИсключение "Нужен свежий Source без прежних link events";
КонецЕсли;
Данные = ПрочитатьПоле85(ДокументПоле85(Форма), 50);
БазаHTML85 = Данные.HTML;
БазаСнимок85 = Данные.Снимок;
Этап85 = 1;
Итог85 = "Фактические 3 строки/12 ячеек подтверждены: количество10, сумма1050. Теперь Шаг85";
#Иначе
ВызватьИсключение "Только толстый управляемый TestManager";
#КонецЕсли
Исключение
Стоп85 = Истина;
Итог85 = "STOP без автоматического повтора: " + ОписаниеОшибки();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Шаг85(Команда)
Если Стоп85 Или Этап85 < 1 Или Этап85 > 3 Тогда
Стоп85 = Истина;
ВызватьИсключение "Неверная фаза; закрыть свой опыт вручную, не повторять после ошибки";
КонецЕсли;
Попытка
Форма = СвояФорма85();
Поле = ДокументПоле85(Форма);
Если Этап85 = 1 Тогда
Если ПрочитатьПоле85(Поле, 50).Снимок <> БазаСнимок85 Тогда
ВызватьИсключение "Перед Input нужен полный подтвержденный собственный baseline";
КонецЕсли;
Поле.ВвестиHTMLДокумента(УчебныйHTMLСтенд85.СвойHTML85(Метка85, 70, Ложь), Новый Соответствие);
ИзмененныйСнимок85 = ПрочитатьПоле85(Поле, 70).Снимок;
Итог85 = "Actual formatted PAPER5×70=350 и полный итог1150. Следующее Шаг85 отдельно перечитывает свое состояние";
ИначеЕсли Этап85 = 2 Тогда
Если ПрочитатьПоле85(Поле, 70).Снимок <> ИзмененныйСнимок85
Или Контроль85(Форма, "Нажатий85") <> "0" Или Контроль85(Форма, "ИтогСсылки85") <> "" Тогда
ВызватьИсключение "Не совпал полный свой formatted snapshot или произошло неожиданное событие HTML";
КонецЕсли;
Итог85 = "Полный formatted snapshot1150 независимо перечитан. Следующее Шаг85 восстанавливает сохраненный native HTML";
ИначеЕсли Этап85 = 3 Тогда
Если ПрочитатьПоле85(Поле, 70).Снимок <> ИзмененныйСнимок85
Или Контроль85(Форма, "Нажатий85") <> "0" Или Контроль85(Форма, "ИтогСсылки85") <> "" Тогда
ВызватьИсключение "Перед Set все собственные строки/поля/counter обязаны совпасть";
КонецЕсли;
Поле.УстановитьHTMLДокумента(БазаHTML85);
Если ПрочитатьПоле85(Поле, 50).Снимок <> БазаСнимок85 Тогда
ВызватьИсключение "Native Set не восстановил полный собственный baseline1050";
КонецЕсли;
Тест85.РазорватьСоединение();
Итог85 = "Ручной native formatted опыт завершен: actual1050→1150→1050. Byte equality и pixel rendering не обещаются; здесь не запускалось";
КонецЕсли;
Этап85 = Этап85 + 1;
Исключение
Стоп85 = Истина;
Итог85 = "STOP: UI мог измениться частично; слепого restore/retry нет. " + ОписаниеОшибки();
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыУчебныйHTMLСтенд85
Своя CF → Общие модули → УчебныйHTMLСтенд85 → Модуль
Server=True ServerCall=True nonglobal/nonprivileged; native HTMLReader/DOM server-local, scalar inputs/outputs.
Функция Паспорт85() Экспорт
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnTestedHTMLInvoice85_6715c6dc-3a27-43c2-a31f-34c44d4c77af\IB"";" Тогда
ВызватьИсключение "Нужен только свой точно подготовленный File-стенд 8.5.1.1343";
КонецЕсли;
Если Метаданные.ОбщиеФормы.Количество() <> 3 Или Метаданные.ОбщиеМодули.Количество() <> 1
Или Метаданные.ОбщиеФормы.Найти("ИсточникHTML85") = Неопределено
Или Метаданные.ОбщиеФормы.Найти("МенеджерHTML85") = Неопределено
Или Метаданные.ОбщиеФормы.Найти("МенеджерФормат85") = Неопределено
Или Метаданные.ОбщиеМодули.Найти("УчебныйHTMLСтенд85") = Неопределено
Или Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Тогда
ВызватьИсключение "Не совпал полный собственный учебный состав CF без прикладных данных";
КонецЕсли;
Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "В своем стенде расширений быть не должно";
КонецЕсли;
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если Пользователь = Неопределено Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Нужен один настоящий собственный пользователь ИБ";
КонецЕсли;
Если Пользователь.Имя <> "HTML85Ученик"
Или Пользователи[0].УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
ВызватьИсключение "Не совпал реальный UUID собственного пользователя ИБ";
КонецЕсли;
Возврат Строка(Пользователь.УникальныйИдентификатор);
КонецФункции
Процедура ПроверитьUUID85(Метка)
Если ТипЗнч(Метка) <> Тип("Строка") Или СтрДлина(Метка) <> 36
Или Строка(Новый УникальныйИдентификатор(Метка)) <> Метка Тогда
ВызватьИсключение "Нужен настоящий canonical UUID своей Source-формы";
КонецЕсли;
КонецПроцедуры
Функция СвойHTML85(Метка, ЦенаБумаги, Ссылка) Экспорт
Паспорт85();
ПроверитьUUID85(Метка);
Если ЦенаБумаги <> 50 И ЦенаБумаги <> 70 Или ТипЗнч(Ссылка) <> Тип("Булево") Тогда
ВызватьИсключение "Допустимы только две собственные цены и явный признак своей ссылки";
КонецЕсли;
ТекстЦены = Формат(ЦенаБумаги, "ЧДЦ=0;ЧГ=0;ЧН=0");
ТекстСуммы = Формат(5 * ЦенаБумаги, "ЧДЦ=0;ЧГ=0;ЧН=0");
HTML = "<html><head><title>Свой счет</title></head><body><h1>OWN:" + Метка + ";</h1><table><tbody>"
+ "<tr><td>BOOK</td><td>2</td><td>250</td><td>500</td></tr>"
+ "<tr><td>PAPER</td><td>5</td><td>" + ТекстЦены + "</td><td>" + ТекстСуммы + "</td></tr>"
+ "<tr><td>TEA</td><td>3</td><td>100</td><td>300</td></tr></tbody></table>";
Если Ссылка Тогда
HTML = HTML + "<a href=""#own-verify-" + Метка + """>Сверить три позиции</a>";
КонецЕсли;
Возврат HTML + "</body></html>";
КонецФункции
Процедура НайтиТаблицу85(Узел, Документ, Найдено, Глубина, Посещено)
Посещено = Посещено + 1;
Если Глубина > 20 Или Посещено > 256 Тогда
ВызватьИсключение "Неожиданно большое собственное HTML-дерево";
КонецЕсли;
Вид = ТипЗнч(Узел);
Если Вид = Тип("ТекстHTML") Тогда
Если ТипЗнч(Узел.ДокументВладелец) <> Тип("ДокументHTML") Или Не Узел.ДокументВладелец.УзелИдентичен(Документ) Тогда
ВызватьИсключение "Текст принадлежит другому документу";
КонецЕсли;
Найдено.Текст = Найдено.Текст + Узел.Данные;
Возврат;
КонецЕсли;
Если Вид <> Тип("ДокументHTML") И Вид <> Тип("ЭлементHTML") И Вид <> Тип("ЭлементЗаголовокHTML")
И Вид <> Тип("ЭлементБлокHTML") И Вид <> Тип("ЭлементТаблицаHTML") И Вид <> Тип("ЭлементСтрокаТаблицыHTML")
И Вид <> Тип("ЭлементЯчейкаТаблицыHTML") И Вид <> Тип("ЭлементФорматированногоТекстаHTML")
И Вид <> Тип("ЭлементЯкорьHTML") И Вид <> Тип("ЭлементМетаHTML") Тогда
ВызватьИсключение "Тип parsed HTML вне собственного ограниченного списка";
КонецЕсли;
Если Вид <> Тип("ДокументHTML") Тогда
Если ТипЗнч(Узел.ДокументВладелец) <> Тип("ДокументHTML") Или Не Узел.ДокументВладелец.УзелИдентичен(Документ) Тогда
ВызватьИсключение "В дереве обнаружен чужой документ-владелец";
КонецЕсли;
Имя = ВРег(Узел.ИмяЭлемента);
Если Имя <> "HTML" И Имя <> "HEAD" И Имя <> "TITLE" И Имя <> "BODY" И Имя <> "H1" И Имя <> "META"
И Имя <> "DIV" И Имя <> "TABLE" И Имя <> "TBODY" И Имя <> "TR" И Имя <> "TD"
И Имя <> "SPAN" И Имя <> "P" И Имя <> "FONT" И Имя <> "B" И Имя <> "I" И Имя <> "U" И Имя <> "A" Тогда
ВызватьИсключение "Неожиданный тег; scripts/images/frames и внешняя загрузка в урок не входят";
КонецЕсли;
КонецЕсли;
Если Вид = Тип("ЭлементТаблицаHTML") Тогда
Если Найдено.Таблица <> Неопределено Тогда
ВызватьИсключение "Нужна ровно одна настоящая собственная таблица";
КонецЕсли;
Найдено.Таблица = Узел;
КонецЕсли;
Дети = Узел.ДочерниеУзлы;
Если ТипЗнч(Дети) <> Тип("СписокУзловHTML") Тогда
ВызватьИсключение "Неверный native тип списка дочерних узлов";
КонецЕсли;
Для Индекс = 0 По Дети.Количество() - 1 Цикл
НайтиТаблицу85(Дети.Элемент(Индекс), Документ, Найдено, Глубина + 1, Посещено);
КонецЦикла;
КонецПроцедуры
Функция ТекстЯчейки85(Узел, Документ, Глубина, Посещено)
Посещено = Посещено + 1;
Если Глубина > 12 Или Посещено > 64 Тогда
ВызватьИсключение "Неожиданная вложенность собственной ячейки";
КонецЕсли;
Вид = ТипЗнч(Узел);
Если Вид <> Тип("ТекстHTML") И Вид <> Тип("ЭлементЯчейкаТаблицыHTML")
И Вид <> Тип("ЭлементHTML") И Вид <> Тип("ЭлементБлокHTML") И Вид <> Тип("ЭлементФорматированногоТекстаHTML") Тогда
ВызватьИсключение "Неподдержанный тип внутри настоящей ячейки";
КонецЕсли;
Если ТипЗнч(Узел.ДокументВладелец) <> Тип("ДокументHTML") Или Не Узел.ДокументВладелец.УзелИдентичен(Документ) Тогда
ВызватьИсключение "Ячейка или текст принадлежат другому документу";
КонецЕсли;
Если Вид = Тип("ТекстHTML") Тогда
Возврат Узел.Данные;
КонецЕсли;
Дети = Узел.ДочерниеУзлы;
Если ТипЗнч(Дети) <> Тип("СписокУзловHTML") Тогда
ВызватьИсключение "Неверный список детей ячейки";
КонецЕсли;
Результат = "";
Для Индекс = 0 По Дети.Количество() - 1 Цикл
Результат = Результат + ТекстЯчейки85(Дети.Элемент(Индекс), Документ, Глубина + 1, Посещено);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПрочитатьТриСтроки85(Документ, Метка, ЦенаБумаги)
Если ТипЗнч(Документ) <> Тип("ДокументHTML") Тогда
ВызватьИсключение "HTMLReader должен вернуть настоящий ДокументHTML, не ДокументDOM";
КонецЕсли;
Найдено = Новый Структура("Таблица,Текст", Неопределено, "");
Посещено = 0;
НайтиТаблицу85(Документ, Документ, Найдено, 0, Посещено);
Если ТипЗнч(Найдено.Таблица) <> Тип("ЭлементТаблицаHTML") Или СтрНайти(Найдено.Текст, "OWN:" + Метка + ";") = 0 Тогда
ВызватьИсключение "Не получены настоящая таблица и собственная видимая метка Source";
КонецЕсли;
Таблица = Найдено.Таблица;
Строки = Таблица.ПолучитьСтроки();
Если ТипЗнч(Строки) <> Тип("КоллекцияЭлементовHTML") Или Строки.Количество() <> 3 Тогда
ВызватьИсключение "Ровно три actual строки обязательны; исходный literal не заменяет результат";
КонецЕсли;
Итог = 0;
Количество = 0;
Снимок = Метка;
Для Индекс = 0 По 2 Цикл
СтрокаHTML = Строки.Элемент(Индекс);
Если ТипЗнч(СтрокаHTML) <> Тип("ЭлементСтрокаТаблицыHTML") Тогда
ВызватьИсключение "Ожидается actual строка HTML, не fabricated data";
КонецЕсли;
Ячейки = СтрокаHTML.Ячейки;
Если ТипЗнч(Ячейки) <> Тип("КоллекцияЭлементовHTML") Или Ячейки.Количество() <> 4 Тогда
ВызватьИсключение "Нужны все четыре настоящие ячейки";
КонецЕсли;
Значения = Новый Массив;
Для Колонка = 0 По 3 Цикл
Ячейка = Ячейки.Элемент(Колонка);
Если ТипЗнч(Ячейка) <> Тип("ЭлементЯчейкаТаблицыHTML") Тогда
ВызватьИсключение "Native коллекция вернула не ячейку";
КонецЕсли;
ПосещеноЯчейки = 0;
Значения.Добавить(СокрЛП(ТекстЯчейки85(Ячейка, Документ, 0, ПосещеноЯчейки)));
КонецЦикла;
Код = ?(Индекс = 0, "BOOK", ?(Индекс = 1, "PAPER", "TEA"));
ОжидаемоеКоличество = ?(Индекс = 0, 2, ?(Индекс = 1, 5, 3));
ОжидаемаяЦена = ?(Индекс = 0, 250, ?(Индекс = 1, ЦенаБумаги, 100));
КоличествоСтроки = Число(Значения[1]);
ЦенаСтроки = Число(Значения[2]);
СуммаСтроки = Число(Значения[3]);
Если Значения[0] <> Код Или КоличествоСтроки <> ОжидаемоеКоличество Или ЦенаСтроки <> ОжидаемаяЦена
Или СуммаСтроки <> КоличествоСтроки * ЦенаСтроки
Или Значения[1] <> Формат(КоличествоСтроки, "ЧДЦ=0;ЧГ=0;ЧН=0")
Или Значения[2] <> Формат(ЦенаСтроки, "ЧДЦ=0;ЧГ=0;ЧН=0")
Или Значения[3] <> Формат(СуммаСтроки, "ЧДЦ=0;ЧГ=0;ЧН=0") Тогда
ВызватьИсключение "Полная строка отличается: код/количество/цена/умножение/числовой формат";
КонецЕсли;
Количество = Количество + КоличествоСтроки;
Итог = Итог + СуммаСтроки;
Снимок = Снимок + ";" + Значения[0] + "|" + Значения[1] + "|" + Значения[2] + "|" + Значения[3];
КонецЦикла;
Если Количество <> 10 Или Итог <> 800 + 5 * ЦенаБумаги Тогда
ВызватьИсключение "Полный независимый итог actual ячеек не совпал";
КонецЕсли;
Возврат Снимок + ";" + Формат(Количество, "ЧДЦ=0;ЧГ=0;ЧН=0") + "|" + Формат(Итог, "ЧДЦ=0;ЧГ=0;ЧН=0");
КонецФункции
Функция Снимок85(HTML, Метка, ЦенаБумаги) Экспорт
Паспорт85();
ПроверитьUUID85(Метка);
Если ТипЗнч(HTML) <> Тип("Строка") Или HTML = "" Или СтрДлина(HTML) > 20000
Или ЦенаБумаги <> 50 И ЦенаБумаги <> 70 Тогда
ВызватьИсключение "Нужен фактический ограниченный HTML и одна из двух своих цен";
КонецЕсли;
Читатель = Новый ЧтениеHTML;
ПерваяОшибка = "";
ОшибкаЗакрытия = "";
Результат = "";
Попытка
Читатель.УстановитьСтроку(HTML);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Читатель);
Результат = ПрочитатьТриСтроки85(Документ, Метка, ЦенаБумаги);
Исключение
ПерваяОшибка = ОписаниеОшибки();
КонецПопытки;
Попытка
Читатель.Закрыть();
Исключение
ОшибкаЗакрытия = ОписаниеОшибки();
КонецПопытки;
Если ПерваяОшибка <> "" Тогда
ВызватьИсключение ПерваяОшибка + ?(ОшибкаЗакрытия = "", "", "; отдельно Close: " + ОшибкаЗакрытия);
КонецЕсли;
Если ОшибкаЗакрытия <> "" Тогда
ВызватьИсключение "HTMLReader.Close: " + ОшибкаЗакрытия;
КонецЕсли;
Возврат Результат;
КонецФункцииИсточникHTML85
Своя CF → Общие формы → ИсточникHTML85 → Модуль
Своя managed Source-форма WindowsThickManaged; server Add/DataPath/SetAction, genuine client events3/1.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Попытка
Пользователь85 = УчебныйHTMLСтенд85.Паспорт85();
Метка85 = Строка(Новый УникальныйИдентификатор);
ЭтаФорма.АвтоЗаголовок = Ложь;
ЭтаФорма.Заголовок = "OwnHTML85 " + Метка85;
Готов85 = Ложь;
Стоп85 = Ложь;
Состояние85 = "WAIT";
Нажатий85 = 0;
ИтогСсылки85 = "";
HTML85 = УчебныйHTMLСтенд85.СвойHTML85(Метка85, 50, Истина);
Формат85 = Новый ФорматированныйДокумент;
Формат85.УстановитьHTML(УчебныйHTMLСтенд85.СвойHTML85(Метка85, 50, Ложь), Новый Структура);
Поле = Элементы.Добавить("HTMLПоле85", Тип("ПолеФормы"));
Поле.Вид = ВидПоляФормы.ПолеHTMLДокумента;
Поле.ПутьКДанным = "HTML85";
Поле.УстановитьДействие("ДокументСформирован", "HTMLГотов85");
Поле.УстановитьДействие("ПриНажатии", "СвояСсылка85");
Поле = Элементы.Добавить("ФорматПоле85", Тип("ПолеФормы"));
Поле.Вид = ВидПоляФормы.ПолеФорматированногоДокумента;
Поле.ПутьКДанным = "Формат85";
Исключение
Стоп85 = Истина;
Состояние85 = "STOP";
Отказ = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура HTMLГотов85(Элемент)
Если Стоп85 Или Элемент <> Элементы.HTMLПоле85 Тогда
Стоп85 = Истина;
Состояние85 = "STOP";
ВызватьИсключение "Неверный источник DocumentComplete или предыдущая ошибка";
КонецЕсли;
Готов85 = Истина;
Состояние85 = "READY";
КонецПроцедуры
&НаКлиенте
Процедура СвояСсылка85(Элемент, ДанныеСобытия, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Попытка
Если Стоп85 Или Не Готов85 Или Элемент <> Элементы.HTMLПоле85 Или Нажатий85 <> 0
Или ТипЗнч(ДанныеСобытия) <> Тип("ФиксированнаяСтруктура") Тогда
ВызватьИсключение "Не свой готовый HTML или ссылка уже была проверена";
КонецЕсли;
Href = ДанныеСобытия.Href;
Фрагмент = "#own-verify-" + Метка85;
Если ТипЗнч(Href) <> Тип("Строка") Или Href <> Фрагмент И Href <> "about:blank" + Фрагмент Тогда
ВызватьИсключение "Разрешен только точный собственный fragment; иной browser base format не угадываем";
КонецЕсли;
ИтогСсылки85 = УчебныйHTMLСтенд85.Снимок85(HTML85, Метка85, 70);
Нажатий85 = Нажатий85 + 1;
Исключение
Стоп85 = Истина;
Состояние85 = "STOP";
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыМодуль управляемого приложения
Своя CF → Модуль управляемого приложения
WindowsThickManaged only, actual native OnStart0/C launch string; открытие только своей формы.
Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентУправляемоеПриложение Тогда
УчебныйHTMLСтенд85.Паспорт85();
Если ПараметрЗапуска = "Source85" Тогда
ОткрытьФорму("ОбщаяФорма.ИсточникHTML85");
ИначеЕсли ПараметрЗапуска = "ManagerHTML85" Тогда
ОткрытьФорму("ОбщаяФорма.МенеджерHTML85");
ИначеЕсли ПараметрЗапуска = "ManagerRich85" Тогда
ОткрытьФорму("ОбщаяФорма.МенеджерФормат85");
Иначе
ВызватьИсключение "Только явный собственный Source85/ManagerHTML85/ManagerRich85";
КонецЕсли;
#Иначе
ВызватьИсключение "Урок разрешает только собственный толстый управляемый клиент";
#КонецЕсли
КонецПроцедурыВторой собственный Manager
Своя CF → Общие формы → МенеджерHTML85 → Модуль
WindowsThickManaged /TestManager, отдельная свежая форма второго опыта; не одновременно управляющие managers.
Перем Тест85;
Перем Этап85;
Перем Стоп85;
Перем Пользователь85;
Перем БазаHTML85;
Перем БазаСнимок85;
Перем ИзмененныйСнимок85;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Этап85 = 0;
Стоп85 = Ложь;
Согласие85 = Ложь;
Метка85 = "";
Итог85 = "Перенесите настоящий UUID своей Source-формы. Сначала отдельное согласие, затем Начать85";
КонецПроцедуры
&НаКлиенте
Функция Поле85(Форма, Имя)
Поле = Форма.ПолучитьОбъект(Тип("ТестируемоеПолеФормы"), , Имя, 3);
Если ТипЗнч(Поле) <> Тип("ТестируемоеПолеФормы") Или Поле.Имя <> Имя
Или Не Поле.ТекущаяВидимость() Или Не Поле.ТекущаяДоступность() Тогда
ВызватьИсключение "Не получено точное настоящее собственное доступное поле";
КонецЕсли;
Возврат Поле;
КонецФункции
&НаКлиенте
Функция Контроль85(Форма, Имя)
Возврат Поле85(Форма, Имя).ПолучитьПредставлениеДанных();
КонецФункции
&НаКлиенте
Функция СвояФорма85()
Если Стоп85 Или Тест85 = Неопределено Или Пользователь85 <> УчебныйHTMLСтенд85.Паспорт85() Тогда
ВызватьИсключение "Предыдущая ошибка или чужой пользователь/стенд";
КонецЕсли;
Формы = Тест85.НайтиОбъекты(Тип("ТестируемаяФорма"), , , 3);
Если ТипЗнч(Формы) <> Тип("ФиксированныйМассив") Или Формы.Количество() <> 1 Тогда
ВызватьИсключение "В TestClient должна быть только одна собственная Source-форма";
КонецЕсли;
Форма = Формы[0];
Если ТипЗнч(Форма) <> Тип("ТестируемаяФорма") Или Форма.ТекстЗаголовка <> "OwnHTML85 " + Метка85
Или Контроль85(Форма, "Метка85") <> Метка85 Или Контроль85(Форма, "Пользователь85") <> Пользователь85
Или Контроль85(Форма, "Состояние85") <> "READY" Тогда
ВызватьИсключение "Не совпали настоящий UUID, пользователь, заголовок или готовность Source";
КонецЕсли;
Возврат Форма;
КонецФункции
&НаКлиенте
Функция ДокументПоле85(Форма)
Поле = Поле85(Форма, "HTMLПоле85");
Если Поле.Вид <> ВидПоляФормы.ПолеHTMLДокумента Или Поле.ТекущееТолькоПросмотр() Тогда
ВызватьИсключение "Не тот actual native kind или настоящее поле readonly";
КонецЕсли;
Возврат Поле;
КонецФункции
&НаКлиенте
Функция ПрочитатьПоле85(Поле, ЦенаБумаги)
HTML = "";
Вложения = Новый Соответствие;
Поле.ПолучитьHTMLДокумента(HTML, Вложения);
Если ТипЗнч(HTML) <> Тип("Строка") Или HTML = "" Или ТипЗнч(Вложения) <> Тип("Соответствие") Или Вложения.Количество() <> 0 Тогда
ВызватьИсключение "Не получены оба настоящих OUT-параметра HTML/Соответствие без вложений";
КонецЕсли;
Снимок = УчебныйHTMLСтенд85.Снимок85(HTML, Метка85, ЦенаБумаги);
Возврат Новый ФиксированнаяСтруктура("HTML,Снимок", HTML, Снимок);
КонецФункции
&НаКлиенте
Процедура Начать85(Команда)
Если Стоп85 Или Этап85 <> 0 Или Не Согласие85 Тогда
Стоп85 = Истина;
ВызватьИсключение "Требуется одно явное согласие на свой TestClient в свежем экземпляре Manager";
КонецЕсли;
Согласие85 = Ложь;
Попытка
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Пользователь85 = УчебныйHTMLСтенд85.Паспорт85();
Если СтрДлина(Метка85) <> 36 Или Строка(Новый УникальныйИдентификатор(Метка85)) <> Метка85 Тогда
ВызватьИсключение "Нужно перенести реальный canonical UUID Source, не генерировать новый";
КонецЕсли;
Тест85 = Новый ТестируемоеПриложение("127.0.0.1", 15387);
Тест85.УстановитьСоединение();
Форма = СвояФорма85();
Если Контроль85(Форма, "Нажатий85") <> "0" Или Контроль85(Форма, "ИтогСсылки85") <> "" Тогда
ВызватьИсключение "Нужен свежий Source без прежних link events";
КонецЕсли;
Данные = ПрочитатьПоле85(ДокументПоле85(Форма), 50);
БазаHTML85 = Данные.HTML;
БазаСнимок85 = Данные.Снимок;
Этап85 = 1;
Итог85 = "Фактические 3 строки/12 ячеек подтверждены: количество10, сумма1050. Теперь Шаг85";
#Иначе
ВызватьИсключение "Только толстый управляемый TestManager";
#КонецЕсли
Исключение
Стоп85 = Истина;
Итог85 = "STOP без автоматического повтора: " + ОписаниеОшибки();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Шаг85(Команда)
Если Стоп85 Или Этап85 < 1 Или Этап85 > 3 Тогда
Стоп85 = Истина;
ВызватьИсключение "Неверная фаза; закрыть свой опыт вручную, не повторять после ошибки";
КонецЕсли;
Попытка
Форма = СвояФорма85();
Поле = ДокументПоле85(Форма);
Если Этап85 = 1 Тогда
Если ПрочитатьПоле85(Поле, 50).Снимок <> БазаСнимок85 Тогда
ВызватьИсключение "Перед Input нужен полный подтвержденный собственный baseline";
КонецЕсли;
Поле.ВвестиHTMLДокумента(УчебныйHTMLСтенд85.СвойHTML85(Метка85, 70, Истина), Новый Соответствие);
ИзмененныйСнимок85 = ПрочитатьПоле85(Поле, 70).Снимок;
Итог85 = "Actual PAPER5×70=350, полный итог1150. Следующее Шаг85 нажимает только свою внутреннюю ссылку";
ИначеЕсли Этап85 = 2 Тогда
Если ПрочитатьПоле85(Поле, 70).Снимок <> ИзмененныйСнимок85 Или Контроль85(Форма, "Нажатий85") <> "0" Тогда
ВызватьИсключение "Перед Click нужны неизменные свои строки и нулевой реальный counter";
КонецЕсли;
Поле.НажатьНаГиперссылкуВHTMLДокументе("Сверить три позиции");
Если Контроль85(СвояФорма85(), "Нажатий85") <> "1"
Или Контроль85(СвояФорма85(), "ИтогСсылки85") <> ИзмененныйСнимок85 Тогда
ВызватьИсключение "Настоящий link handler не подтвердил ровно одно срабатывание и actual1150";
КонецЕсли;
Итог85 = "Реальное событие Source0→1 и полный снимок1150 отдельно совпали. Следующее Шаг85 восстанавливает свой baseline";
ИначеЕсли Этап85 = 3 Тогда
Если ПрочитатьПоле85(Поле, 70).Снимок <> ИзмененныйСнимок85
Или Контроль85(Форма, "Нажатий85") <> "1" Или Контроль85(Форма, "ИтогСсылки85") <> ИзмененныйСнимок85 Тогда
ВызватьИсключение "Текущее измененное состояние не принадлежит успешному своему процессу";
КонецЕсли;
Поле.ВвестиHTMLДокумента(БазаHTML85, Новый Соответствие);
Если ПрочитатьПоле85(Поле, 50).Снимок <> БазаСнимок85 Тогда
ВызватьИсключение "Полный actual baseline1050 не восстановлен";
КонецЕсли;
Тест85.РазорватьСоединение();
Итог85 = "Ручной native опыт завершен: actual1050→1150→1050; реальный link counter1. Здесь этот запуск не выполнялся";
КонецЕсли;
Этап85 = Этап85 + 1;
Исключение
Стоп85 = Истина;
Итог85 = "STOP: UI мог измениться частично; слепого restore/retry нет. " + ОписаниеОшибки();
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыРазбор по шагам
Сначала создайте только свою пустую CF и формы по подготовке. COMMON/Source/APPLICATION и оба MAIN — полные модули, никаких неизвестных входных объектов.
Начать85 требует отдельного согласия и настоящий Source UUID. Actual TestApplication→ровно oneForm→TestedField/name/kind/visibility/enable/readOnly. Сохранить фактически прочитанные HTML и полный baseline snapshot1050.
Первое Шаг85: полный текущий baseline перед Input, собственное изменение только PAPER50→70. Сразу проверить все12 actual ячеек, qty10/1150, не вычислить «успех» из отправленного HTML.
Второе Шаг85: Native Input→два OUT Get→отдельная полная сверка→Set1 сохраненного baseline→новый actual Get.
Третье Шаг85: повторно подтвердить весь собственный changed snapshot и счетчик, только затем restore; проверить новый полный native baseline1050 и разорвать только свое testing соединение. При любой ошибке sticky STOP без слепого отката/повтора.
Как проверить результат
Будущий manual result: BOOK2/250/500, PAPER5/50/250→5/70/350→5/50/250, TEA3/100/300; количество10, суммы1050→1150→1050 из настоящих parsed ячеек.
HTML-урок отдельно подтверждает Source event counter0→1 и полный scalar снимок1150. Formatted-урок не нажимает гиперссылку и требует HTML counter0/empty.
Unknown type/kind/form/UUID/readonly/parsed HTML shape/extra rows/changed price/state/event/cleanup останавливает опыт. Статический PASS не является выполненным GUI/1С результатом.
Ожидаемый результат
Ожидаемый результат будущего ручного выполнения: полный own three-row native readback1050→1150→1050; у HTML ровно одно настоящее событие своей ссылки. Здесь runtime не выполнялся.
На что обратить внимание
Нельзя вызвать GetDocumentHTML() без двух OUT или присвоить его результат: native return не объявлен. Нельзя передать Структура вместо tested Соответствие; серверный Formatted API имеет иной контракт.
Internal @Tested registry owner не runtime type. Нужны настоящий TestedFormField и readonly kind от documented factory; extension конструкторов нет.
Formatted Click исключен: реальный source event owner не доказан; Form.URLProcessing для надписей нельзя подменить событием formatted поля. SaveToFile2 исключены: thin-only testing/file/dialog не memory task.
HTMLReader→DOMBuilder — положительно documented HTML parser. DocumentHTML.GetElementsByName возвращает DOM list по native и здесь не применяется; actual HTML nodes получены только ChildNodes.Item и typed guards.
Native HTML может быть преобразован; код не обещает точную исходную разметку, сохранение произвольных тегов, browser DOM/COM API/pixels или отмену перехода через Standard=False.
Этот HTML-парсер понимает только описанную структуру собственного счета; при других типах узлов, тегах или составе строк опыт останавливается без подстановки ожидаемых значений.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.