当前位置: 代码迷 >> 综合 >> Watir Popup对象处理
  详细解决方案

Watir Popup对象处理

热度:45   发布时间:2024-01-12 03:30:24.0

Watir基于处理,继承于web,document的对象提供较好的支持方法,但相对于处理windows对象较弱. 就目前从各网站收集的对象来看, 基本上,对于在IE实例对象打开的web标准对象能够成功识别与操作,其它的脱离当前IE窗口,打开的所有弹出框都不能正常识别。其中,弹出框对象占有异常对象识别中很大一部分。

目前碰到的弹出框, 我把他们分为三大类型:

 

1, Alerts 警告作用,如:sorry, 当前用户没有权限操作

2, Confirm 需要操作按钮, 如:你确认要删除当前记录?

3, Prompt+ select +confirm  需要用户输入,操作查询或点击, 最后确认, 如:Download/upload (浏览+选择文件)

 

下面给出,上面几种弹出框watir实现识别与操作的方法,

5.1. 弹出框基于autoIT + 线程实现方式

此种方法,对于第一、二种弹出框操作较有效,

因点击某个link/button等对象,而弹出的窗口(大部分弹出框可应用此种方式来实现。)

1, 定义方法

def check_for_popups

    autoit = WIN32OLE.new(’AutoItX3.Control’)

    #

    # Do forever - assumes popups could occur anywhere/anytime in your application.

    loop do

        # Look for window with given title. Give up after 1 second.

        ret = autoit.WinWait(’消息 — 网页对话框’, ”, 1)

        #ret = WinActivate(”Microsoft Internet Explorer”, “”)

       #autoit.ControlClick(”Microsoft Internet Explorer”, “”, “[CLASS:Button; INSTANCE:1]“, 2)

        puts(ret)

        #

        # If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).

        if (ret==1) then autoit.Send(”{Enter}”) end

        #

        # Take a rest to avoid chewing up cycles and give another thread a go.

        # Then resume the loop.

        sleep(3)

    end

  end

程序体代码

ie.button(:name, “signin”).click_no_wait

sleep(20)

$popup = Thread.new { check_for_popups }  # start popup handler

at_exit { Thread.kill($popup) }

 

 Call 另一ruby文件

对于第二种弹出框,像安全警告点击, 并不通过操作与点击任何对象, 即呈现弹出窗口。

我尝试用3.1方法来实现,不成功。用下面方法替代:
1, 在watir/WindowHelper.rb文件中增加方法

   def push_security_alert_yes_cn

        @autoit.WinWait “安全警报”, “”

        @autoit.Send “{TAB}”

        @autoit.Send “{TAB}”

        @autoit.Send “{SPACE}”

      End

2, 定义另一调用文件 tmp.rb

require ‘watir/WindowHelper’

helper = WindowHelper.new

helper.push_security_alert_cn_yes
3, 在打开安全URL之前,启动调用ruby文件

require ‘rubygems’

require ‘watir’   # the watir controller

require ‘win32ole’

require ‘watir/WindowHelper’
Thread.new{system(’ruby c:/tmp.rb’)} #你定义tmp文件存放路径

ie = Watir::IE.new

ie.goto(”http://www.alipay.com.cn/“)

 

修改框架底层

此种方法,针对弹出框3.

举例一, 上传下载文件

1, 修改底层代码input_elements.rb文件,

类 FileField中, 方法set.

为了支持中文,有一句替换修改为:

system(”rubyw -e /”require ‘win32ole’; @autoit=WIN32OLE.new(’AutoItX3.Control’);waitresult=@autoit.WinWait

选择文件’, ”, 15; sleep 1; if waitresult == 1/” -e
/”@autoit.ControlSetText ‘选择文件’, ”, ‘Edit1′, ‘#{setPath}’;
@autoit.ControlSend ‘选择文件’, ”, ‘Button2′, ‘{ENTER}’;/” -e /”end/”")
2, 定义方法

def save_file(filepath)

    ai = WIN32OLE.new(”AutoItX3.Control”)

    ai.WinWait(”文件下载”, “”, 5)

    ai.ControlFocus(”文件下载”, “”, “保存(&S)”)

    sleep 1

    ai.ControlClick(”文件下载”, “”, “保存(&S)”, “left”)

    ai.WinWait(”另存为”, “”, 5)

    sleep 1

    ai.ControlSend(”另存为”, “”, “Edit1″,filepath)

    ai.ControlClick(”另存为”, “”, “保存(&S)”, “left”)

    ai.WinWait(”下载完毕”, “”, 5)

    ai.ControlClick(”下载完毕”, “”, “关闭”)

  end
3, 程序体代码:

ie.file_field(:name, “xlsfile”).set(”c://samenameobject.html”)

#上传你所指定的文件

ie.span(:text, “导出Excel表”).click_no_wait

save_file(”C://abc.xls”)

#下载到你所指定的路径

 

针对弹出框3, 需要用户介入查询并操作:

举例二, 中供crm中类目与客户选择的弹出框,与第一种实现方式不同在于,

用到autoit中WinActivate与ControlClick方法,
require ‘rubygems’

require ‘watir’   # the watir controller

 require ‘watir/WindowHelper’

 

require ‘win32ole’
def check_for_popups

 

autoit = WIN32OLE.new(’AutoItX3.Control’)

loop do

      ret = autoit.Winwait(”选择 — 网页对话框”, “”, 1)

      puts ret

     if (ret==1) then

       autoit.WinActivate(”[CLASS:Internet Explorer_TridentDlgFrame]“, “”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{TAB}”)

      #autoit.Send(”湖州”)

      #autoit.Send(”{ASC 2709}”)

      #autoit.SendUnicode(”a”)

      #autoit.ClipPut (”杭”)

      #autoit.ClipGet

      #autoit.ToolTip “This is a tooltip杭州”, 0, 0

      #autoit.Sleep 2000  

 

      autoit.Send(”{TAB}”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{Enter}”)

      autoit.WinActivate(”[CLASS:Internet Explorer_TridentDlgFrame]“, “”)

      autoit.ControlClick(”选择 — 网页对话框”, “”, “[CLASS:Internet Explorer_TridentLstBox; INSTANCE:2]“, 2)

      autoit.Send(”{TAB}”)

      autoit.Send(”{Enter}”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{TAB}”)

      autoit.Send(”{Enter}”)

    end

    sleep(3)

  end

end
ie=Watir::IE.new

ie.goto(”http://10.2.6.4:5100/bin/member/signin“)

#ie.goto(”http://10.2.6.4:5100/“)
#ie.element_by_xpath(”//span[contains(text(), 'Main Road Nijmegen')]“).click

ie.text_field(:name, “id”).set(”mhl1805″) 

ie.text_field(:name, “password”).set(”zxcvbnm”)

ie.button(:name, “signin”).click
ie.frame(:name, “left”).link(:url, “http://10.2.6.4:5100/v3/help_cust.htm”).click

ie.frame(:name, “left”).link(:text, “新签中供客户”).click

 # start popup handler
ie.frame(:name, “right”).frame(:name, “rtop”).button(:value, “选择客户”).click_no_wait

sleep(20)

$popup = Thread.new { check_for_popups }

at_exit { Thread.kill($popup) }

针对第三种popup window, 如果需要与用户交互,且需要输入中文时,若用autoit sendkey对待中文支持(但官方文档说支持中文输入, 网上有不少人和我遇到同样问题),尚没有找到有效方案,有待进一步跟进。

   除上述弹出框需要特殊处理外,watir中也有一些扩展tag,或第三方控件需要特殊处理的,

   像:

 

web HTML编辑器

中文站的html编辑器提供: 操作ID或name操作起来较方便直接

require ‘rubygems’

require ‘watir’   # the watir controller

require ‘watir/WindowHelper’

require ‘win32ole’

ie=Watir::IE.new

ie=Watir::IE.attach(:title, /阿里助手/)

 

ie.text_field(:name, “_fmo.a._0.s”).set(”mhl1805″) 

ie.document.getElementByid(”_editor”).contentWindow.focus()

ie.send_keys(”abcsadfasfd”)
但也碰到有些web页面,不提供任何ID,只能用autoIT方法来send tab实现
require ‘rubygems’

require ‘watir’   # the watir controller

require ‘watir/WindowHelper’

require ‘win32ole’

 
ie=Watir::IE.new

#ie=Watir::IE.attach(:title, /Alibaba/)

ie.goto(’http://us.my.alibaba.com/product/buyoffer/post_buying_lead.htm’)

ie.text_field(:name, “_fmp.bu._0.su”).set(”mhl1805″) 

ie.text_field(:name, “_fmp.bu._0.su”).set(”中国人”) 
ie.checkbox(:id, “detailDesc”).set

ie.checkbox(:id, “detailDesc”).focus()

ie.send_keys(”/t”*9)

ie.send_keys(’Hello Worldabcdef’)


对象识别其它常用TAG内置方法引用

如:IE.div , ie.span, ie.cell, ie.table方法,可以实现点击操作,取值操作等.

另外提供QTP

类似描述性编程,同类型对象统计:

ie.buttons.each { |b| puts b.to_s }

 puts ie.checkboxes.length  

 puts ie.links.length 

 puts ie.buttons.length等等 

对于常用的innertext属性, 在watir中已经封装到方法,可以直接引用。如:

ruby在对象识别底层,封装了innertext

实现,调用方法text即可:

如:puts ie.div(:id, “intelligentWord”).link(:id, index.to_s).text

最后:返回文本与源代码,用下面方法:

puts ie.text()

puts ie.html() 

 

识别对象正则表达式支持

当然,ruby提供强大的正则表达式支持,如:属性标识正则

ie=Watir::IE.attach(:title, /Alibaba/)

Ruby的正则表达式以”//”作为基本框架,表达式内容位于”/”之间。表达式返回一个RegExp的对象。

表达式的一般规则:

/a/匹配字符a。

//?/匹配特殊字符?。特殊字符包括^, $, ? , ., /, /, [, ], {, }, (, ), +, *.

.匹配任意字符,例如/a./匹配ab和ac。

/[ab]c/匹配ac和bc,[]之间代表范围。例如:/[a-z]/ , /[a-zA-Z0-9]/。

/[^a-zA-Z0-9]/匹配不在该范围内的字符串。

/[/d]/代表任意数字,/[/w]/代表任意字母,数字或者_,/[/s]/代表空白字符,包括空格,TAB和换行。

/[/D]/,/[/W]/,/[/S]/均为上述的否定情况。

关于正则其它用法,请参照《watir技术集锦》

最后攻略

总之,对于对象识别与操作,要借助于上述文档中的, 灵活运用autoit, xpath与异常对象操作方法。对于watir不支持的windows控件,想到第一个方法,就是采用第三方autoit技术,来模拟键盘或鼠标操作。

对于操作web对象,watir不支持特殊tag,除了扩展其底层代码外,只能深深研究一下xpath了.

最后,再搞不定,就只能到watir group里咨询高人了,呵呵。

尚没有碰到其它更好方法。。。

 

 

但是针对以上几种方法,我曾经在测试自己公司产品的logout功能时,一直都不能实现。

后来寻求到另一种解决方案,代码如下:

require 'watir'
def check_for_popups(title="Microsoft Internet Explorer", button="OK")
    popup=Thread.new {
        autoit=WIN32OLE.new('AutoItX3.Control')
        ret=autoit.WinWait(title,"",60)
        if (ret==1)
            puts "There is popup."
            autoit.WinActivate(title)
            button.downcase!
            if button.eql?("ok") || button.eql?("yes") || button.eql?("continue")
                autoit.Send("{Enter}")
            else
                autoit.Send("{tab}")
                autoit.Send("{Enter}")
            end
        elsif (ret==0)
            puts "No popup, please check your code."
        end
    }
    at_exit { Thread.kill(popup) }
end

$ie.link(:text,//).click_no_wait
check_for_popups("Microsoft Internet Explorer", "OK")
这个方法针对 Popup是 OK/cancel之类的弹出框比较有效。


针对PopUp box的官方解决方法:
http://wiki.openqa.org/display/WTR/JavaScript+Pop+Ups