Запуск javascript из qtp
Автор Bek, 15 сен 2006 11:18
Сообщений в теме: 9
#1
Отправлено 15 сентября 2006 - 11:18
Заголовок неинформативный, попробую тут точнее.
На тестируемой странице есть javascript функция. Каким образом ее можно запустить во время прогона теста? Хочется что нибудь вида
browser(...).....execscript "scriptname", "params,.."
Заранее спасибо
На тестируемой странице есть javascript функция. Каким образом ее можно запустить во время прогона теста? Хочется что нибудь вида
browser(...).....execscript "scriptname", "params,.."
Заранее спасибо
#2
Отправлено 19 сентября 2006 - 11:54
вопрос снят.
посмотрел на проблему с другой стороны.
Descriptive programming - отличная штука!!! =)
посмотрел на проблему с другой стороны.
Descriptive programming - отличная штука!!! =)
#3
Отправлено 19 сентября 2006 - 13:28
В принципе, ответ на исходный вопрос надо было-бы искать в MSDN - в описании DOM IE (MSHTML4). QTP предоставляет доступ к элементам DOM чераз свойство тестовых объектов .object. Я думаю, что если можно как-то вызвать javascript из QTP - то только так - вызовом соответствующего метода соответствующего элемента DOM (если таковой существует - не уверен в этом), либо путём DHTML-программирования прямо из QTP (то есть - создаёте в DOM элемент, вызывающий javascript по определённому событию, а потом инициируете это событие для этого элемента).
Best regards,
Майк.
Майк.
#4
Отправлено 21 сентября 2006 - 07:39
я так и пытался сначала.
сначала возникала ошибка 80020101, потом вообще 'unrecognised error'. в общем отложил на потом
сначала возникала ошибка 80020101, потом вообще 'unrecognised error'. в общем отложил на потом
#5
Отправлено 21 сентября 2006 - 13:42
Мне, честно говоря, интересно, как Вы это делали. Можете поделиться соответствующими кусками кода? (QTP Vbscript + HTML). Мне кажется, задача должна быть вполне выполнима, интересно - как именно. Думаю, может пригодиться не только мне и Вам, но и другим участникам форума.
Best regards,
Майк.
Майк.
#6
Отправлено 22 сентября 2006 - 14:09
ну, как я и писал, сначала подошел не с той стороны.
идея такая. есть страница, сгенеренная из .aspx, в ней форма. форма передает данные из таблицы посредством jscript функции __DoPostBack. Она на вход принимает id элемента строки web таблицы. Этот элемент кроме id ничем от соседей не отличается.
Вот начало формы и функция:
всякое неважное пропущено. А вот две строки из таблицы. Функция отправки формы постится по клику на "Edit":
1 подход: Выдрать из таблицы аргументы функции __doPostBack вида:
сама функция.
Пример: надо кликнуть по "Edit" на второй строке. Значит надо передать id из второго ряда массива на вход функции __doPostBack. Попробовал такое:
В тесте:
в общем нерабочая конструкция получилась.
идея такая. есть страница, сгенеренная из .aspx, в ней форма. форма передает данные из таблицы посредством jscript функции __DoPostBack. Она на вход принимает id элемента строки web таблицы. Этот элемент кроме id ничем от соседей не отличается.
Вот начало формы и функция:
<body MS_POSITIONING="GridLayout"> <form name="Form1" method="post" action="default.aspx" id="Form1"> <input type="hidden" name="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" value="" /> <input type="hidden" name="__VIEWSTATE" value="XXXXXXXXXXXX" /> <script language="javascript" type="text/javascript"> <!-- function __doPostBack(eventTarget, eventArgument) { var theform; if (window.navigator.appName.toLowerCase().indexOf("microsoft") > -1) { theform = document.Form1; } else { theform = document.forms["Form1"]; } theform.__EVENTTARGET.value = eventTarget.split("$").join(":"); theform.__EVENTARGUMENT.value = eventArgument; theform.submit(); } // --> </script>
всякое неважное пропущено. А вот две строки из таблицы. Функция отправки формы постится по клику на "Edit":
<tr align="Center"> <td> <span id="repeaterConfig__ctl1_txtCTID">type1</span></td> <td> <span id="repeaterConfig__ctl1_txtPPID">BMP04</span></td> <td> <span id="repeaterConfig__ctl1_txtCPID">BMC09</span></td> <td> <span id="repeaterConfig__ctl1_txtAW">11000</span></td> <td> <span id="repeaterConfig__ctl1_txtIsActive">Y</span></td> <td> <input id="repeaterConfig__ctl1_chkRemove" type="checkbox" name="repeaterConfig:_ctl1:chkRemove" /> </td> <td> <a id="repeaterConfig__ctl1_btnEdit" href="javascript:__doPostBack('repeaterConfig$_ctl1$btnEdit','')">Edit</a></td> </tr> <tr align="Center"> <td> <span id="repeaterConfig__ctl2_txtCTID">type2</span></td> <td> <span id="repeaterConfig__ctl2_txtPPID">BMP05</span></td> <td> <span id="repeaterConfig__ctl2_txtCPID">BMC03</span></td> <td> <span id="repeaterConfig__ctl2_txtAW">12</span></td> <td> <span id="repeaterConfig__ctl2_txtIsActive">Y</span></td> <td> <input id="repeaterConfig__ctl2_chkRemove" type="checkbox" name="repeaterConfig:_ctl2:chkRemove" /> </td> <td> <a id="repeaterConfig__ctl2_btnEdit" href="javascript:__doPostBack('repeaterConfig$_ctl2$btnEdit','')">Edit</a></td> </tr>
1 подход: Выдрать из таблицы аргументы функции __doPostBack вида:
[COLOR=red]repeaterConfig$_ctl1$btnEdit[/COLOR]выделенное сохранить в двумерный массив вместо неинформативного "Edit" (в массив таблица перегонялась немного переделанной функцией tableSaveToArray2D (table,Byref arr) © Mike ). Примерно так:
GetPostBackLink Replace(cstr(oTable.rows(i).cells(colcount-1).innerhtml),vbCrLf,"\n"), strFromRegExp Arr(i,colcount-1) = strFromRegExp
сама функция.
Public Function GetPostBackLink(strHtml, ByRef strLink) Dim re, Matches Set re = New RegExp GetPostBackLink = false re.Global = True re.Pattern = "<a.*\('(.+)'," re.IgnoreCase = True Set Matches = re.Execute(strHtml) Set strLink = Matches(1) Reporter.ReportEvent micWarning, "Matches", strLink GetPostBackLink = true End FunctionС помощью полученного массива уже можно ковыряться в данных.
Пример: надо кликнуть по "Edit" на второй строке. Значит надо передать id из второго ряда массива на вход функции __doPostBack. Попробовал такое:
В тесте:
EditLink = "repeaterConfig$_ctl2$btnEdit" ClickEditButton (EditLink, Page)Здесь Page - это Browser("..").Page(".."), то есть то, что сейчас тестируется.
Public Function ClickEditButton (EditLink, Page) Dim script script = "var theform;if (window.navigator.appName.toLowerCase().indexOf(""microsoft"") > -1) {theform = document.Form1; } else {theform = document.forms[""Form1""];} theform.__EVENTTARGET.value = EditLink.split(""$"").join("":""); theform.__EVENTARGUMENT.value = ''; theform.submit();" Page.object.parentWindow.execScript(script) ClickEditButton = true End FunctionА это эмуляция клика =)))
в общем нерабочая конструкция получилась.
#7
Отправлено 22 сентября 2006 - 14:13
то, что получилось после, намного проще =)
Сохраняем таблицу также, как указано выше. а нужный Edit кликаем по индексу:
Сохраняем таблицу также, как указано выше. а нужный Edit кликаем по индексу:
'Create description object for 'Edit' links Set Desc = Description.Create() Desc("text").Value = "Edit" Desc("Index").Value = 2 .Link(Desc).Click
#8
Отправлено 22 сентября 2006 - 14:37
Даааа.... Первый вариант меня до слёз пронял Вот уж действительно, "мы не ищем лёгких путей..." далее по тексту . Что за ошибка у Вас возникала могу сказать - если никаких ошибок в скрипте не допустили, это должно было быть что-то типа Permission Denied по причине Cross-Frame security ограничений. Увы, никак не получится вызвать ни один метод .ParentWindow - доблестный IE не позволит - проверял . Я-то думал, что проблема - вызвать скрипт, который не вызывается ни одним существующим элементом. Соответственно идея была - добавить такой элемент и вызвать ему событие по которому он вызовет скрипт.
Что-ж до моей несчастной функции, то, конечно, в первом варианте она была не ахти
Вот модернизированный вариант:
Этот вариант умеет работать с ColSpan'ами (то есть, слившимися ячейками)
Что-ж до моей несчастной функции, то, конечно, в первом варианте она была не ахти
Вот модернизированный вариант:
'@Documentation returns empty 2d-array function Empty2DArray() Dim resArr ReDim resArr(-1,-1) Empty2DArray = resArr end function Private function getMaxColCount(domTable) Dim RowIterator Dim ColIterator Dim CurColCountSoFar Dim MaxColCountSoFar MaxColCountSoFar=0 For RowIterator = 0 to domTable.rows.Length-1 CurColCountSoFar=0 For ColIterator = 0 to domTable.rows(RowIterator).Cells.Length-1 CurColCountSoFar=CurColCountSoFar+domTable.rows(RowIterator).Cells(ColIterator).ColSpan Next MaxColCountSoFar = Max(MaxColCountSoFar,CurColCountSoFar) Next getMaxColCount = MaxColCountSoFar End Function '@Documentation Save WebTable <table> content (e.g. cells innertext) into 2D-array <arr>. Capture method - simple (only text cells are captured) '// Simple version - embedded controls and ROWspans are ignored, Colspans are handled Public Function tableSaveToArray2D_Simple (table,Byref resArr) arr = Empty2DArray() If Not isObject(Table) Then Reporter.ReportEvent micWarning,"tableSaveAsArray2D","Invalid parameter (table)!" Exit Function End If If Not Table.exist(10) Then Reporter.ReportEvent micWarning,"tableSaveToArray2D_simple","Table not found!" Exit Function End If Dim sFilter sFilter = Reporter.Filter Reporter.Filter=2 set oTable = table.Object rowCount = oTable.Rows.Length 'Determining maximal columns count (since columns count may vary from row to row) Dim colCount,curColCount,rowCount Dim oTable,oRow colCount = getMaxColCount(oTable) curColCount = empty 'variable will be re-used, so we re-initialize it. 'Capturing table data to array Redim resArr(rowCount-1,colCount-1) Dim actualColIndex,curColSpan Dim curCell For rowIterator = 0 to rowCount-1 actualColIndex=0 curColCount = oTable.rows(rowIterator).cells.Length For colIterator = 0 To curColCount-1 On Error Resume Next set curCell=oTable.rows(rowIterator).cells(colIterator) 'Merged cell in webtable is represented as curColSpan cells in resArr. curColSpan = empty curColSpan = curcell.ColSpan err.clear resArr (rowIterator,actualColIndex) = ProcessInnerText(CStr(curCell.innertext)) If Err.description <> "" Then resArr(rowIterator,actualColIndex) = "" Err.Clear end if actualColIndex = actualColIndex + curColSpan On Error goto 0 Next Next Reporter.Filter=sFilter tableSaveToArray2D_simple = true End Function
Этот вариант умеет работать с ColSpan'ами (то есть, слившимися ячейками)
Best regards,
Майк.
Майк.
#9
Отправлено 22 сентября 2006 - 15:07
Посмотрел ещё раз. Врубился. Идея, на самом деле была хороша - и код вполне симпатичный. Оценил . Но, действительно, подошли сначала не с того конца. А вот насчёт ExecScript... Вы пробовали отлаживаться - запихивать туда скрипт попроще (например, пустой, который ничего не делает)? Получалось? Я, конечно, предполагаю, что работать не должно, но вот как там на самом деле... В общем, надо проверить
Best regards,
Майк.
Майк.
#10
Отправлено 25 сентября 2006 - 13:09
Так самое смешное, что пустой скрипт выполняется. Даже не совсем пустой тоже выполняется =)
если в вышеприведенной функции от скрипта оставить только объявление "var theform;", то все работает!!!
ЗЫ в прошлый раз неправильно кусок кода привел - надо как здесь:
Public Function ClickEditButton (EditLink, Browser) Dim script script = "var theform;if (window.navigator.appName.toLowerCase().indexOf(""microsoft"") > -1) {theform = document.Form1; } else {theform = document.forms[""Form1""];} theform.__EVENTTARGET.value = EditLink.split(""$"").join("":""); theform.__EVENTARGUMENT.value = ''; theform.submit();" Reporter.ReportEvent micDone, "Form", script Browser.Object.document.parentWindow.execScript(script) ClickEditButton = true End Function
если в вышеприведенной функции от скрипта оставить только объявление "var theform;", то все работает!!!
ЗЫ в прошлый раз неправильно кусок кода привел - надо как здесь:
Browser.Object.document.parentWindow.execScript(script)
Количество пользователей, читающих эту тему: 0
0 пользователей, 0 гостей, 0 анонимных