Каждую историю можно рассказать, разматывая каждое слово до предложения. А можно строго по делу. Я увы не умею ни того, ни другого. Надеюсь, получится нечто среднее. Начнем...
Идея № 1: инъекция в веб-интерфейс
Идея № 2: эмуляция событий клавиатуры через WScript.Shell
Собственно в заголовке все сказано. Начальный механизм такой-же, COM объект браузера, переход на сайт и попытка ввести данные в активированное поле. Собственно идея провалилась, события отправлялись в само 1С предприятие которое создало COM объект IE. Может я что-то курил не верно, но победить не смог. В итоге, идея была отметена.
Идея № 3: а что если инструменты тестирования web-приложений могут помочь
Настройка Selenium Webdriver
Сразу оговорюсь, я выбрал Javascript как самый простой для себя вариант. Конечно. (как в известной шутке) с Google я программирую на многих языках, но в случае с JS помощь поисковика особо не требуется. Да и эксперимент удался, решено было на этой базе и продолжить.
- Установить selenium-webdriver (npm)
- В каталог "PATH" (что это) положить необходимый вам драйвер для браузера. Chrome и Firefox наименее капризные. IE x86 в принципе тоже не сильно вредный, но вот с IE x64 нужны отдельные танцы с бубном. Об этом читайте ниже.
- Объявляете 'selenium-webdriver'
var wd = require('selenium-webdriver');
Как работать далее очень доходчиво описано в инструкции. Я же расскажу о том, что мы делали далее и об особенностях взаимодействия с веб-клиентом 1С.
Подключили, молодцы. Что дальше?
Поскольку нам необходимо было данные брать из подготовленных пользователями Excel файлов, было решено следующее. Файлов много, они требуют предварительной обработки перед внесением в формы веб-клиента. Значит нужно написать загрузку данных в максимально простые и удобные формы конфигурации пустышки, опубликовать http-сервисы и данные "подсасывать" из нее, отдавая туда всю информацию о результатах загрузки. В итоге написано два интерфейса с одним адресом, но разными способами обращения и параметрами.
- GET. localhost/test/hs/data/doc?user=name. Принимал параметром пользователя от имени которого загружаются данные. В итоге отдавал JSON пакет с данными максимально удобными для внесения
- POST. localhost/test/hs/data/doc?user=name&result=str. Параметром уже принимает имя пользователя и результат выполнения. Если результат = error, тогда в теле передавался полный лог, от момента авторизации, до момента ошибки.
Поскольку все взаимодействие с клиентом браузера у Selenium построено на promise-ах (это что-то вроде ОбработчикОповещения в 1С, подробнее лучше почитать тут) вести лог достаточно просто.
Как проверить данные в веб-клиенте.
Большинство данных в поля можно вносить несколькими способами: либо Код, либо Наименование, либо значение другого реквизита. Поскольку мы не имели доступа к конфигурации, это было выяснено опытным путем. Большинство справочников было выгружено стандартными "Вывести список" или загружено через единственный интерфейс загрузки НСИ. В итоге, мы решили что данные будут вводиться кодами или другими реквизитами (не представлениями), а результат подбора будет проверяться на соответствие представления. Т.е. кратко это выглядит так:
client.findElement(by.id('userName'))
.sendKeys('username')
.then(check_UserName)
.then(function() {
console.log('OK');
})
.catch(function() {
console.log('error', 'Значение не равно userName');
});
function check_UserName() {
return new Promise(checkInputValue_promise);
function checkInputValue_promise(resolve, reject) {
var element = client.findElement(by.id('userName'));
element.getAttribute('value')
.then(function (attrText) {
var i = attrText.trim();
if (i !== 'username') {
reject(false);
}
else {
resolve(true);
}
});
}
}
Кроме того проверялись результаты введенных данных в табличных полях, путем считывания ячеек подвала с итогами и сравнением с расчетными величинами данных из пакета.
Некоторые нюансы работы веб-клиента:
- Когда редактируете строку табличной части, на самом деле все input-ы под каждую ячейку уже существуют, поэтому после нажатия sednkeys-Enter можно проверять доступность следующего поля. Имена полей как правило выглядят следующим образом: Form[N]_ИмяПоля_i0, где N - порядковый номер созданной формы, ИмяПоля - имя поля как оно задано в конфигураторе (можно изучить Profiler-ом). i0 - существует всегда, как я понял
- С нумерацией форм все совсем весело. Дело в том, что если форма полностью перестраивается, то старый контейнер <div id='formN_container'> очищается, создается новый, со следующим номером и в него добавляются все вложенные элементы. Я лечил достаточно просто, когда я понял как изменяется форма после редактирования полей, я просто добавил проверку на изменения номера формы. Сделать это не сложно. Можно пойти путем поиска по следующему пути (нотация xpath) //div[@id='VW_page1formContent']/div[@class='IWebForm']. Собственно последний div и будет вашей формой. А номер "pageN" можно получить по заголовку окна. Впрочем если вы создаете объекты последовательно, то можно просто отследить порядок создания элементов платформой.
- После окончания редактирования, всегда следует проверять следующий элемент на доступность и видимость, при необходимости отправлять туда Click для активации.
- Не забывайте о штатном поведении форм 1С, при вводе данных происходит переход на следующее поле. Окончание редактирования последней ячейки приводит к автометическому созданию новой строки. Так что лучше не делать в последнем поле Enter, а либо переходить в следующий элемент, либо вызывать Click на кнопке Добавить.
- Диалоги вопросов о записи (или закрытии) формы могут быть в отдельном iFrame, следует это учитывать и подключаться к нему соответствующими методами webdriver-а.
Выводы
Веб-клиент 1С вполне пригоден для тестирования, очень даже понятен и хорошо написан. Конечно, есть вопросы к строению дерева HTML страницы, но им виднее. Все необходимые программные компоненты (js, конфигурации, веб-сервисы) были реализованы примерно за одну неделю. Даже сделана попытка реализовать работу в автоматическом режиме, с перезапуском, логированием и прочими плюшками для анализа результата.
Как итог, силами двух компьютеров данные были внесены за примерно 4 дня работы. Не учитывая первый день, когда отлавливались баги, дописывались забытые catch-и и наведен порядок в описании логов, а то по началу было сложно понять где и почему произошел отказ.
Причины в основном были кстати следующие:
- Код не соответствовал наименованию. Лечилось корректировкой данных в исходниках;
- Программа не дождалась перехода следующего поля в видимость и/или доступность. Лечилось попытками с подсчетом, в случае превышения лимита - завершение клиента, создание нового и повторный ввод данных. Край перезапуск.
- Клиент отвалился. Не лечилось. Перезапуск.
- Была добавлена попытка закрыть текущую форму, чтобы не записывать некорректные данные. Перезапуск.
- Очистка поля иногда приводит к появлению символа 'a' перед вводимым значением. Не лечилось. Перезапуск.
По логам потом отслеживали какие данные не внесены, проверяли и отправляли повторно. На 2000 документов было около 50 ошибочных доков. Проверились за 20 минут вручную и были перезапущены повторно, после чего все село корректно.
Самый главный итог: веб-клиент 1С был подвергнут тестированию и показал хороший результат. Собственно наработки были использованы для тестирования некоторых наших веб-морд клиентов, что выявило некоторые неудобства работы и внесены изменения в конфигурации. А сам веб-клиент - это дорого реализованный продукт. Денег и труда туда вложено прилично.
Бонус. Настройка IE x64
Практически все тонкости настройки описаны тут, но некоторые нюансы опущены. Сразу говорю, у меня IE 11, win 10, x64.
- Копируем в PATH драйвер для x64 (тыц)
- Вносим изменения в реестр (подробнее в этом разделе)
- Настраиваем параметры безопасности (Свойства браузера - Безопасность). Для всех зон ставим "Включить защищенный режим"
- Включаем 64-х разрядные процессы для браузера (Свойства браузера - Дополнительно). Ставим галочку "Включить 64-разрядные процессы для расширенного защищенного режима". Попутно проверяем что "Включить расширенный защищенный режим" выключен
На этом в принципе все, после этого IE должен быть более стабильным, а скорость печати будет выше, чем у 100летней бабушки. НО: если не поможет, ставите 32-х битный драйвер, отключаете 64-разрядные процессы (п.4) и работать тоже будет. Возможно даже разницы не заметите.
Послесловие
node "путь к файлу"/setdata_wsors.js
Все должно случиться. В файле есть некоторые вспомогательные методы с описаниями. Возможно для евангелистов мой код покажется ужасным, прошу сильно не пинать и направить на путь истинный.
P.S. прошу также не пинать за платность файла. Будем считать это скромным "спасибо" за данную статью если она оказалась полезной. Если тема будет интересна, работу с Selenium можно осветить подробнее.