Перейти к содержимому

Фотография

Запуск javascript из qtp


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 9

#1 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 15 сентября 2006 - 11:18

Заголовок неинформативный, попробую тут точнее.

На тестируемой странице есть javascript функция. Каким образом ее можно запустить во время прогона теста? Хочется что нибудь вида
browser(...).....execscript "scriptname", "params,.."

Заранее спасибо
  • 0

#2 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 19 сентября 2006 - 11:54

вопрос снят.
посмотрел на проблему с другой стороны.
Descriptive programming - отличная штука!!! =)
  • 0

#3 Mike

Mike

    Консультант

  • Members
  • PipPipPipPipPipPip
  • 1 079 сообщений
  • Город:Москва

Отправлено 19 сентября 2006 - 13:28

В принципе, ответ на исходный вопрос надо было-бы искать в MSDN - в описании DOM IE (MSHTML4). QTP предоставляет доступ к элементам DOM чераз свойство тестовых объектов .object. Я думаю, что если можно как-то вызвать javascript из QTP - то только так - вызовом соответствующего метода соответствующего элемента DOM (если таковой существует - не уверен в этом), либо путём DHTML-программирования прямо из QTP (то есть - создаёте в DOM элемент, вызывающий javascript по определённому событию, а потом инициируете это событие для этого элемента).
  • 0
Best regards,
Майк.

#4 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 21 сентября 2006 - 07:39

я так и пытался сначала.
сначала возникала ошибка 80020101, потом вообще 'unrecognised error'. в общем отложил на потом
  • 0

#5 Mike

Mike

    Консультант

  • Members
  • PipPipPipPipPipPip
  • 1 079 сообщений
  • Город:Москва

Отправлено 21 сентября 2006 - 13:42

Мне, честно говоря, интересно, как Вы это делали. Можете поделиться соответствующими кусками кода? (QTP Vbscript + HTML). Мне кажется, задача должна быть вполне выполнима, интересно - как именно. Думаю, может пригодиться не только мне и Вам, но и другим участникам форума.
  • 0
Best regards,
Майк.

#6 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 22 сентября 2006 - 14:09

ну, как я и писал, сначала подошел не с той стороны.
идея такая. есть страница, сгенеренная из .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 :blush: ). Примерно так:
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
А это эмуляция клика =)))

в общем нерабочая конструкция получилась.
  • 0

#7 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 22 сентября 2006 - 14:13

то, что получилось после, намного проще =)

Сохраняем таблицу также, как указано выше. а нужный Edit кликаем по индексу:

'Create description object for 'Edit' links
Set Desc = Description.Create() 
Desc("text").Value = "Edit"
Desc("Index").Value = 2
.Link(Desc).Click

  • 0

#8 Mike

Mike

    Консультант

  • Members
  • PipPipPipPipPipPip
  • 1 079 сообщений
  • Город:Москва

Отправлено 22 сентября 2006 - 14:37

Даааа.... Первый вариант меня до слёз пронял :blush: Вот уж действительно, "мы не ищем лёгких путей..." далее по тексту :dirol: . Что за ошибка у Вас возникала могу сказать - если никаких ошибок в скрипте не допустили, это должно было быть что-то типа Permission Denied по причине Cross-Frame security ограничений. Увы, никак не получится вызвать ни один метод .ParentWindow - доблестный IE не позволит - проверял :crazy: . Я-то думал, что проблема - вызвать скрипт, который не вызывается ни одним существующим элементом. Соответственно идея была - добавить такой элемент и вызвать ему событие по которому он вызовет скрипт.

Что-ж до моей несчастной функции, то, конечно, в первом варианте она была не ахти :focus:
Вот модернизированный вариант:
'@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'ами (то есть, слившимися ячейками)
  • 0
Best regards,
Майк.

#9 Mike

Mike

    Консультант

  • Members
  • PipPipPipPipPipPip
  • 1 079 сообщений
  • Город:Москва

Отправлено 22 сентября 2006 - 15:07

Посмотрел ещё раз. Врубился. Идея, на самом деле была хороша - и код вполне симпатичный. Оценил :dirol: . Но, действительно, подошли сначала не с того конца. А вот насчёт ExecScript... Вы пробовали отлаживаться - запихивать туда скрипт попроще (например, пустой, который ничего не делает)? Получалось? Я, конечно, предполагаю, что работать не должно, но вот как там на самом деле... В общем, надо проверить :blush:
  • 0
Best regards,
Майк.

#10 Bek

Bek

    Новый участник

  • Members
  • Pip
  • 23 сообщений
  • Город:СПб

Отправлено 25 сентября 2006 - 13:09

Так самое смешное, что пустой скрипт выполняется. Даже не совсем пустой тоже выполняется =)
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 гостей, 0 анонимных