Расширение тестируемого поля формы для форматированного документа

Типы · Tested form field extension for a formatted document

Содержит свойства, специфичные для поля вида ПолеФорматированногоДокумента.

Полное описание, параметры и ограничения

Расширение тестируемого поля формы для форматированного документа (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 не выполнялся.

Подготовка

  1. Это будущий ручной опыт только в собственной Windows VM. Новая File CF УчебныйHTMLТестСчет85: C:\1c-labs\OwnTestedHTMLInvoice85_6715c6dc-3a27-43c2-a31f-34c44d4c77af\IB; точная платформа8.5.1.1343, основной режим УправляемоеПриложение, совместимость НеИспользовать. UUID каталога — метка стенда, не UUID ИБ. Стенд/CF/процессы/порты здесь не создавались.

  2. С нуля создайте ровно три общие управляемые формы ИсточникHTML85, МенеджерHTML85, МенеджерФормат85; один общий модуль УчебныйHTMLСтенд85 и свою роль HTML85ПолныеПрава. Прикладных объектов/данных/расширений нет. В роли разрешите Администрирование для native GetUsers и открытие своих общих форм. Один реальный пользователь HTML85Ученик с этой ролью; никакого чужого аккаунта.

  3. COMMON из supportingModules: общий модуль УчебныйHTMLСтенд85, СерверДа, ВызовСервераДа, ГлобальныйНет, ПривилегированныйНет, оба КлиентНет, ВнешнееСоединениеНет, ПовторноеИспользованиеВозвращаемыхЗначенийНеИспользовать. Из клиентов передаются только строки/число/Булево; HTMLReader/DOM/Formatted native объекты остаются в разрешенном контексте.

  4. ИсточникHTML85: реквизиты Метка85/Пользователь85 Строка36, HTML85 Строка неограниченная, Формат85 ФорматированныйДокумент, Готов85/Стоп85 Булево, Нажатий85 Число5.0, ИтогСсылки85/Состояние85 Строка неограниченная. HTMLПоле85/ФорматПоле85 руками не создавайте: код Add→actual ПолеФормы→Вид→ПутьКДанным делает это на сервере.

  5. В Source разместите только readonly обычные поля Метка85, Пользователь85, Состояние85, Нажатий85, ИтогСсылки85, одноименные DataPath. Для Нажатий85 задайте Формат="ЧДЦ=0;ЧГ=0;ЧН=0". Событие ПриСозданииНаСервере назначьте одноименной процедуре. Полный SOURCE поддерживает ПриНажатии3 и ДокументСформирован1 через native SetAction. Не вызывайте эти обработчики вручную.

  6. У обеих manager-форм реквизиты Метка85 Строка36/поле, Согласие85 Булево/флажок и Итог85 Строка неограниченная/readonly поле. Событие ПриОткрытии→ПриОткрытии(Отказ). Две команды Начать85 и Шаг85, Действие — одноименные процедуры с одним параметром Команда; две кнопки с соответствующим ИмяКоманды. В МенеджерHTML85 вставьте MAIN первого урока, в МенеджерФормат85 — MAIN второго. Ни один модуль не должен быть подставлен в неизвестную форму.

  7. Модуль управляемого приложения — полный APPLICATION. Назначьте ПриНачалеРаботыСистемы. Source/manager открываются только по своему /C. В списке баз у своей регистрации явно выберите клиент Толстый клиент; /RunModeManagedApplication учитывает эту настройку. Сам #Если ТолстыйКлиентУправляемоеПриложение откажет при другом клиенте; один ключ запуска не доказывает actual client.

  8. Установленная справка1cv8_ru.hbk zif2_testclient подтверждает /TestClient [-TPort<Номер TCP-порта>] для толстого/тонкого; zif2_TestManager — /TestManager также для обоих. Человек предварительно проверяет, что127.0.0.1:15387 свободен и используется только своими двумя приложениями. Никакой automated launch/port/network check в этом уроке не выполняется.

  9. Первый ручной запуск: "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/файлы/пароли/производственные пути. Закройте Конфигуратор перед опытом.

  10. Второй ручной запуск того же собственного стенда и пользователя: тот же executable/ENTERPRISE/F/N/RunModeManagedApplication, но /TestManager /C "ManagerHTML85" для первого урока или /C "ManagerRich85" для второго. Source должен быть единственной открытой формой TestClient; настоящий UUID из его Метка85 перенесите в Manager. Каждый урок начинайте двумя свежими собственными запусками, не повторно после STOP.

  11. Данные в памяти: BOOK2×250=500; PAPER5×50=250; TEA3×100=300. Количество10/итог1050. Единственное изменение PAPER50→70 дает350/1150; возврат PAPER50 восстанавливает1050. У каждой строки читаются actual код/количество/цена/сумма из native HTML, не из запроса, literal или подготовленного golden.

  12. GetDocumentHTML имеет два обязательных OUT-параметра HTML:Строка и Вложения:Соответствие, не return. У серверного FormattedDocument.SetHTML вложения обязательны и Структура; у tested Input optional Соответствие. У tested Formatted.SetDocumentHTML тип optional вложений не объявлен: в коде только один обязательный HTML, никаких догадок.

  13. HTML link — лишь внутренний #own-verify-actualUUID. OnClick данные.Href только scalar; COM-методы браузера не вызываются. Допускаются exact fragment или exact about:blank+fragment, иное форматирование URL честно отказывает. Standard=False не отменяет действие по native; это НЕ sandbox/security/url blocker.

  14. Дождитесь собственной Source-готовности. Начать85→Шаг85 три раза. Каждый следующий шаг перечитывает полный own state; после ошибки текущий Manager/Source не сбрасываются, restore/retry/закрытие чужих окон/удаление данных отсутствуют. Если форматирование преобразовало HTML так, что полный typed snapshot не читается, зафиксируйте STOP, не подставляйте ожидаемые ячейки.

  15. Здесь написанный урок и статические проверки 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 нет. " + ОписаниеОшибки();
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры

Разбор по шагам

  1. Сначала создайте только свою пустую CF и формы по подготовке. COMMON/Source/APPLICATION и оба MAIN — полные модули, никаких неизвестных входных объектов.

  2. Начать85 требует отдельного согласия и настоящий Source UUID. Actual TestApplication→ровно oneForm→TestedField/name/kind/visibility/enable/readOnly. Сохранить фактически прочитанные HTML и полный baseline snapshot1050.

  3. Первое Шаг85: полный текущий baseline перед Input, собственное изменение только PAPER50→70. Сразу проверить все12 actual ячеек, qty10/1150, не вычислить «успех» из отправленного HTML.

  4. Второе Шаг85: Native Input→два OUT Get→отдельная полная сверка→Set1 сохраненного baseline→новый actual Get.

  5. Третье Шаг85: повторно подтвердить весь собственный changed snapshot и счетчик, только затем restore; проверить новый полный native baseline1050 и разорвать только свое testing соединение. При любой ошибке sticky STOP без слепого отката/повтора.

Как проверить результат

  1. Будущий manual result: BOOK2/250/500, PAPER5/50/250→5/70/350→5/50/250, TEA3/100/300; количество10, суммы1050→1150→1050 из настоящих parsed ячеек.

  2. HTML-урок отдельно подтверждает Source event counter0→1 и полный scalar снимок1150. Formatted-урок не нажимает гиперссылку и требует HTML counter0/empty.

  3. 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 не выполнялся.

На что обратить внимание

  1. Нельзя вызвать GetDocumentHTML() без двух OUT или присвоить его результат: native return не объявлен. Нельзя передать Структура вместо tested Соответствие; серверный Formatted API имеет иной контракт.

  2. Internal @Tested registry owner не runtime type. Нужны настоящий TestedFormField и readonly kind от documented factory; extension конструкторов нет.

  3. Formatted Click исключен: реальный source event owner не доказан; Form.URLProcessing для надписей нельзя подменить событием formatted поля. SaveToFile2 исключены: thin-only testing/file/dialog не memory task.

  4. HTMLReader→DOMBuilder — положительно documented HTML parser. DocumentHTML.GetElementsByName возвращает DOM list по native и здесь не применяется; actual HTML nodes получены только ChildNodes.Item и typed guards.

  5. Native HTML может быть преобразован; код не обещает точную исходную разметку, сохранение произвольных тегов, browser DOM/COM API/pixels или отмену перехода через Standard=False.

  6. Этот HTML-парсер понимает только описанную структуру собственного счета; при других типах узлов, тегах или составе строк опыт останавливается без подстановки ожидаемых значений.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.