super-test 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGE.txt +9 -0
  3. data/README.txt +13 -0
  4. data/bin/idb +19 -0
  5. data/bin/ii +113 -0
  6. data/bin/istart_mock +36 -0
  7. data/bin/istop_mock +16 -0
  8. data/bin/kk +181 -0
  9. data/bin/rubyatp +42 -0
  10. data/bin/start_mock +36 -0
  11. data/bin/stop_mock +16 -0
  12. data/bin/xgo +45 -0
  13. data/conf/conf.rb +11 -0
  14. data/conf/db03.yml +31 -0
  15. data/conf/db13.yml +37 -0
  16. data/conf/db19.yml +33 -0
  17. data/conf/online.yml +32 -0
  18. data/conf/super_test.yml +40 -0
  19. data/conf/system.yml +26 -0
  20. data/conf/sz00.yml +31 -0
  21. data/conf/sz06.yml +34 -0
  22. data/conf/wise00.yml +11 -0
  23. data/data/case.house +0 -0
  24. data/data/char.house +0 -0
  25. data/data/images/Bluehills.jpg +0 -0
  26. data/data/images/Sunset.jpg +0 -0
  27. data/data/images/Waterlilies.jpg +0 -0
  28. data/data/images/Winter.jpg +0 -0
  29. data/data/query.house +18595 -0
  30. data/data/user.house +8 -0
  31. data/lib/action/module/check_action.rb +58 -0
  32. data/lib/action/module/cnnt_action.rb +161 -0
  33. data/lib/action/module/datacenter_action.rb +48 -0
  34. data/lib/action/module/http_pack_helper.rb +163 -0
  35. data/lib/action/module/httpserver_action.rb +297 -0
  36. data/lib/action/module/inc.rb +21 -0
  37. data/lib/action/module/mcpack_action.rb +57 -0
  38. data/lib/action/module/sql_action.rb +84 -0
  39. data/lib/action/module/ssh_action.rb +37 -0
  40. data/lib/action/system/user_action.rb +180 -0
  41. data/lib/common/appium_helper.rb +217 -0
  42. data/lib/common/atp_helper.rb +74 -0
  43. data/lib/common/atp_report.rb +344 -0
  44. data/lib/common/data_house.rb +405 -0
  45. data/lib/common/data_model.rb +87 -0
  46. data/lib/common/http/assert_helper.rb +343 -0
  47. data/lib/common/http/fix_hpricot.rb +118 -0
  48. data/lib/common/http/html_helper.rb +362 -0
  49. data/lib/common/http/http_helper.rb +469 -0
  50. data/lib/common/http/multipart.rb +81 -0
  51. data/lib/common/isandbox_helper.rb +195 -0
  52. data/lib/common/json_helper.rb +43 -0
  53. data/lib/common/mock_helper.rb +168 -0
  54. data/lib/common/mtop_helper.rb +141 -0
  55. data/lib/common/myconf_helper.rb +49 -0
  56. data/lib/common/mylog_helper.rb +77 -0
  57. data/lib/common/pairwise.rb +121 -0
  58. data/lib/common/query_house.rb +89 -0
  59. data/lib/common/report_helper.rb +97 -0
  60. data/lib/common/robot_helper.rb +85 -0
  61. data/lib/common/socket/check.rb +325 -0
  62. data/lib/common/socket/conf_modifier.rb +149 -0
  63. data/lib/common/socket/context.rb +55 -0
  64. data/lib/common/socket/data.rb +392 -0
  65. data/lib/common/socket/data_helper.rb +41 -0
  66. data/lib/common/socket/env.rb +317 -0
  67. data/lib/common/socket/inc.rb +24 -0
  68. data/lib/common/socket/log.rb +213 -0
  69. data/lib/common/socket/log4s.rb +58 -0
  70. data/lib/common/socket/log_helper.rb +332 -0
  71. data/lib/common/socket/my_sql.rb +77 -0
  72. data/lib/common/socket/net.rb +74 -0
  73. data/lib/common/socket/network.rb +115 -0
  74. data/lib/common/socket/rlib/conf_modifier.rb +130 -0
  75. data/lib/common/socket/rlib/data_helper.rb +33 -0
  76. data/lib/common/socket/rlib/log_helper.rb +303 -0
  77. data/lib/common/socket/rlib/process_helper.rb +91 -0
  78. data/lib/common/socket/stub.rb +276 -0
  79. data/lib/common/socket/util.rb +266 -0
  80. data/lib/patterns/inc.rb +10 -0
  81. data/lib/patterns/mc_base_pattern.rb +474 -0
  82. data/lib/patterns/some_pattern.rb +145 -0
  83. data/lib/super_test.rb +114 -0
  84. data/log/super_test.log +0 -0
  85. data/log/super_test.log.wf +0 -0
  86. data/test/cover_me.rb +6 -0
  87. data/tool/jenny +0 -0
  88. data/tool/mcsend/mcsend2 +0 -0
  89. data/tool/mcsend/mcsend2_shead +0 -0
  90. data/tool/mcserver/conf/mcserver.conf +77 -0
  91. data/tool/mcserver/conf/mcserverauthip +17 -0
  92. data/tool/mcserver/mcserver +0 -0
  93. data/tool/mcserver/mcserver_trans +0 -0
  94. data/tool/mysql +0 -0
  95. data/tool/net/mcsend/mcsend +0 -0
  96. data/tool/net/mcsend/mcsend_trans +0 -0
  97. data/tool/net/mcsend/nshead.data +7 -0
  98. data/tool/net/mcsend/res_nshead.data +7 -0
  99. data/tool/net/my_client/my_client +0 -0
  100. data/tool/net/tsclient/client.tcl +205 -0
  101. data/tool/others/kk +190 -0
  102. data/tool/others/rubyatp +42 -0
  103. data/tool/others/supertest_install.sh +34 -0
  104. data/tool/trip/idb +0 -0
  105. data/tool/ts-agent/nshead.bft +12 -0
  106. data/tool/ts-agent/server.conf +10 -0
  107. data/tool/ts-agent/server.tcl +376 -0
  108. metadata +275 -0
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ #
4
+ # Author:: hanyu
5
+ # Date:: 2009.5.7
6
+
7
+ if __FILE__ == $0
8
+ $LIB_ROOT = "#{File.dirname(__FILE__)}/.."
9
+ $TEST_ROOT = "#{$LIB_ROOT}/.."
10
+ $: << "#{$LIB_ROOT}"
11
+ require 'common/log_helper'
12
+ require 'common/config_helper'
13
+ end
14
+
15
+
16
+ # User 表示一个用户
17
+ # 目前的实现只是一个普通的数据模型,没有行为
18
+ class User
19
+
20
+ attr_accessor :name, :password, :url, :portrait, :sex
21
+
22
+ # 创建User
23
+ # - name 用户名,必填项
24
+ # - password 密码,选填项,默认值 passme123
25
+ # - url url前缀名,选填项,默认与name相同
26
+ # - portrait 头像加密串,选填项,默认为nil
27
+ # - sex 性别,1男,2女,默认值1
28
+ #
29
+ # Example #1:
30
+ #
31
+ # user_A = User.new "ruguo"
32
+ # user_B = User.new "ruguo2","1234"
33
+ # user_C = User.new "ruguo4","1234","ruguo","fl3k2jr23jr5o2u5o214"
34
+ def initialize(name, password=ConfigHelper::CONF['default_password'], url=name, portrait=nil, sex=1)
35
+ # 用户名
36
+ @name = name
37
+ # 用户密码
38
+ @password = password
39
+ # 空间url
40
+ @url = url
41
+ # 头像加密串 uid+uname
42
+ @portrait = portrait
43
+ # 性别
44
+ @sex = sex
45
+ end
46
+
47
+ # 重载之,方便日志打印
48
+ #
49
+ # Example #1:
50
+ #
51
+ # user = User.new "ruguo","pass","ruguo"
52
+ # puts user
53
+ # # => #<User:0x00000000b19220 @name="ruguo", @password="pass", @space_url="ruguo", @portrait=nil>
54
+ def to_s
55
+ inspect
56
+ end
57
+
58
+ # 重载==,方便User对象之间的比较
59
+ #
60
+ # Example #1:
61
+ #
62
+ # a = User.new "ruguo","pass","ruguo"
63
+ # b = User.new "ruguo","pass33","ruguo33"
64
+ # c = User.new "ruguo11","pass33","ruguo33"
65
+ # d = Object.new
66
+ #
67
+ # puts a == b #=> true
68
+ # puts a == c #=> false
69
+ # puts a == d #=> false
70
+ def ==(obj)
71
+ obj.kind_of?(User) and obj.name == @name
72
+ end
73
+
74
+ end
75
+
76
+ if __FILE__ == $0
77
+ u = User.new "ruguo","pass","ruguo"
78
+ p u
79
+ puts u
80
+ b = User.new "ruguo","pass33","ruguo33"
81
+ c = User.new "ruguo1","pass","ruguo33"
82
+ d = Object.new
83
+ puts u == b
84
+ puts u == c
85
+ puts u == d
86
+ end
87
+
@@ -0,0 +1,343 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ #
4
+ # Author:: hanyu
5
+ # Date:: 2009.5.7
6
+
7
+ if __FILE__ == $0
8
+ $LIB_ROOT = "#{File.dirname(__FILE__)}/.."
9
+ $TEST_ROOT = "#{$LIB_ROOT}/.."
10
+ $: << "#{$LIB_ROOT}"
11
+ require 'common/log_helper'
12
+ require 'common/config_helper'
13
+ require 'common/http_helper'
14
+ require 'common/html_helper'
15
+ end
16
+
17
+
18
+ # case中尽量使用经过封装的assert
19
+ #
20
+ # - 扩展assert方法,支持html、json等解析
21
+ # - 自定义上层可读message
22
+ # - 打印可读日志
23
+ module AssertHelper
24
+
25
+ # === 功能:
26
+ # 验证返回码是200
27
+ #
28
+ # === 参数解释:
29
+ # - msg 失败之后的提示文字
30
+ #
31
+ # === Example:
32
+ # Example:
33
+ # get "hi.baidu.com"
34
+ # assert_ok
35
+ def assert_ok(msg=nil)
36
+ return if @is_press
37
+ raise "must send http request before assert!" if @response == nil
38
+ msg = "assert_ok fail!" if msg.nil?
39
+ assert_equal @response.code, "200", msg
40
+ $log.debug "assert_ok success!"
41
+ end
42
+
43
+ # === 功能:
44
+ # 验证HTTP请求的返回码
45
+ #
46
+ # === 参数解释:
47
+ # - code Fixnum,返回码
48
+ # - msg 失败之后的提示文字
49
+ #
50
+ # === Example:
51
+ # Example:
52
+ # get "http://www.google.com/not_exist_page"
53
+ # assert_code 404
54
+ def assert_code(code, msg=nil)
55
+ return if @is_press
56
+ raise "must send http request before assert!" if @response == nil
57
+ msg = "assert_code fail!" if msg.nil?
58
+ assert_equal @response.code, code.to_s, msg
59
+ $log.debug "assert_code code[#{code}] success!"
60
+ end
61
+
62
+ # === 功能:
63
+ # 验证重定向
64
+ #
65
+ # === 参数解释:
66
+ # - url 要跳转的url
67
+ # - msg 失败之后的提示文字
68
+ #
69
+ # === Example:
70
+ # Example:
71
+ # get "http://hi.baidu.com/sys/not_exist_page"
72
+ # assert_redirected_to "error.html"
73
+ def assert_redirected_to(url, msg=nil)
74
+ return if @is_press
75
+ raise "must send http request before assert!" if @response == nil
76
+ msg = "assert_redirected_to fail!" if msg.nil?
77
+ assert_equal @response.code, "302", msg
78
+ assert @response.header.key?("Location"), msg
79
+ assert_equal @response.header["Location"], url, msg
80
+ $log.debug "assert_redirected_to url[#{url}] success!"
81
+ end
82
+
83
+ # === 功能:
84
+ # grep方式匹配
85
+ #
86
+ # === 参数解释:
87
+ # - regexp 正则表达式
88
+ # - msg 失败之后的提示文字
89
+ #
90
+ # === Example:
91
+ # get "http://hi.baidu.com/"
92
+ # assert_grep /百度空间/
93
+ #
94
+ def assert_grep(regexp, msg=nil)
95
+ return if @is_press
96
+ raise "must send http request before assert!" if @response == nil
97
+ msg = "assert_grep fail!" if msg.nil?
98
+ assert_match regexp, @response.body, msg
99
+ $log.debug "assert_grep regexp[#{regexp}] success!"
100
+ end
101
+
102
+ # === 功能:
103
+ # 见 assert_grep
104
+ def assert_no_grep(regexp,msg=nil)
105
+ return if @is_press
106
+ raise "must send http request before assert!" if @response == nil
107
+ msg = "assert_no_grep fail!" if msg.nil?
108
+ exp = /#{Regexp.escape(regexp)}/ if String === regexp
109
+ assert_no_match exp, @response.body, msg
110
+ $log.debug "assert_no_grep regexp[#{regexp}] success!"
111
+ end
112
+
113
+ # === 功能:
114
+ # 断言包含某字符串
115
+ #
116
+ # === 参数解释:
117
+ # - str 字符串,不能是正则表达式
118
+ # - msg 失败之后的提示文字
119
+ #
120
+ # === Example:
121
+ # get "http://hi.baidu.com/"
122
+ # assert_has "百度空间", "something wrong!"
123
+ def assert_has(str,msg=nil)
124
+ return if @is_press
125
+ assert find_has?(str), msg
126
+ $log.debug "assert_has str[#{str}] success!"
127
+ end
128
+ # === 功能:
129
+ # 与assert_has相反
130
+ def assert_has_not(str,msg=nil)
131
+ return if @is_press
132
+ assert !find_has?(str), msg
133
+ $log.debug "assert_has_not str[#{str}] success!"
134
+ end
135
+
136
+ # === 功能:
137
+ # 断言元素存在
138
+ #
139
+ # === 参数解释:
140
+ # - xpath 定位,可以使xpath or selector
141
+ # - msg 失败之后的提示文字
142
+ #
143
+ def assert_exist(xpath, msg=nil, &blk)
144
+ return if @is_press
145
+ msg = "assert_exist xpath[#{xpath}] fail!" if msg.nil?
146
+ assert find_exist?(xpath,&blk), msg
147
+ $log.debug "assert_exist xpath[#{xpath}] success!"
148
+ end
149
+
150
+ # === 功能:
151
+ # 断言元素不存在
152
+ #
153
+ # === 参数解释:
154
+ # - xpath 定位,可以使xpath or selector
155
+ # - msg 失败之后的提示文字
156
+ #
157
+ def assert_no_exist(xpath, msg=nil, &blk)
158
+ return if @is_press
159
+ msg = "assert_no_exist xpath[#{xpath}]" if msg.nil?
160
+ assert_false find_exist?(xpath,&blk), msg
161
+ $log.debug "assert_no_exist xpath[#{xpath}] success!"
162
+ end
163
+
164
+ # === 功能:
165
+ # 验证某元素内text的内容
166
+ #
167
+ # === 参数解释:
168
+ # - xpath 定位,可以使xpath or selector
169
+ # - regexp 期待的结果,可以是正则表达式
170
+ # - msg 失败之后的提示文字
171
+ #
172
+ # === Example:
173
+ # Example #1:
174
+ # get "http://hi.baidu.com/"
175
+ # assert_text "#m_space", "更多精彩空间"
176
+ #
177
+ def assert_text(xpath, regexp, msg=nil, &blk)
178
+ return if @is_press
179
+ raise "must send http request before assert!" if @response == nil
180
+ expect = find_text xpath, &blk
181
+ msg = "assert_text xpath[#{xpath}] regexp[#{regexp}] fail!" if msg.nil?
182
+ assert_match regexp, expect, msg
183
+ $log.debug "assert_text xpath[#{xpath}] regexp[#{regexp}] success!"
184
+ end
185
+
186
+ # === 功能:
187
+ # 见 assert_text
188
+ def assert_no_text(xpath, regexp, msg=nil, &blk)
189
+ return if @is_press
190
+ raise "must send http request before assert!" if @response == nil
191
+ expect = find_text xpath, &blk
192
+ exp = /#{Regexp.escape(regexp)}/ if String === regexp
193
+ msg = "assert_no_text xpath[#{xpath}] regexp[#{regexp}] fail!" if msg.nil?
194
+ assert_no_match exp, expect, msg
195
+ $log.debug "assert_no_text xpath[#{xpath}] regexp[#{regexp}] success!"
196
+ end
197
+
198
+ # === 功能:
199
+ # 验证某元素的html片段的内容
200
+ #
201
+ # === 参数解释:
202
+ # - xpath 定位,可以使xpath or selector
203
+ # - regexp 期待的结果,可以是正则表达式
204
+ # - msg 失败之后的提示文字
205
+ #
206
+ # === Example:
207
+ # Example #1:
208
+ # get "http://hi.baidu.com/"
209
+ # assert_html "#m_space", "更多精彩空间"
210
+ #
211
+ # Example #2:
212
+ # get "http://hi.baidu.com/"
213
+ # assert_html "//div[@id='m_space']", "更多精彩空间"
214
+ def assert_html(xpath, regexp, msg=nil, &blk)
215
+ return if @is_press
216
+ raise "must send http request before assert!" if @response == nil
217
+ expect = find_html xpath, &blk
218
+ msg = "assert_html xpath[#{xpath}] regexp[#{regexp}] fail!" if msg.nil?
219
+ assert_match regexp, expect, "assert_html xpath[#{xpath}] regexp[#{regexp}] fail!"
220
+ $log.debug "assert_html xpath[#{xpath}] regexp[#{regexp}] success!"
221
+ end
222
+
223
+ # === 功能:
224
+ # 见 assert_html
225
+ def assert_no_html(xpath, regexp, msg=nil, &blk)
226
+ return if @is_press
227
+ raise "must send http request before assert!" if @response == nil
228
+ expect = find_html xpath, &blk
229
+ exp = /#{Regexp.escape(regexp)}/ if String === regexp
230
+ msg = "assert_no_html xpath[#{xpath}] regexp[#{regexp}] fail!" if msg.nil?
231
+ assert_no_match exp, expect, msg
232
+ $log.debug "assert_no_html xpath[#{xpath}] regexp[#{regexp}] success!"
233
+ end
234
+
235
+ # === 功能:
236
+ # 验证某Element的属性值
237
+ #
238
+ # === 参数解释:
239
+ # - xpath 定位,可以使xpath or selector
240
+ # - attr 属性名
241
+ # - regexp 期待的结果,可以是正则表达式
242
+ # - msg 失败之后的提示文字
243
+ #
244
+ # === Example:
245
+ # Example:
246
+ # get "http://hi.baidu.com/"
247
+ # assert_attr "div#m_space div.t1 a.grnlk", "href" "http://hi.baidu.com/hi/more/wonderful/"
248
+ # # html代码片段
249
+ # # <div id="m_space">
250
+ # # <div class="t1">
251
+ # # <a href="http://hi.baidu.com/hi/more/wonderful/" target="_blank" class="grnlk"><img src="http://img.baidu.com/hi/img/index/i1.gif" border="0" align="top"> 空间中的海外华人 </a>
252
+ # # ...
253
+ def assert_attr(xpath, attr, regexp, msg=nil, &blk)
254
+ return if @is_press
255
+ raise "must send http request before assert!" if @response == nil
256
+ expect = find_attr xpath, attr, &blk
257
+ msg = "assert_attr xpath[#{xpath}] attr[#{attr}] regexp[#{regexp}] fail!" if msg.nil?
258
+ assert_match regexp, expect, msg
259
+ $log.debug "assert_attr xpath[#{xpath}] attr[#{attr}] regexp[#{regexp}] success!"
260
+ end
261
+
262
+ # === 功能:
263
+ # 见 assert_attr
264
+ def assert_no_attr(xpath, attr, regexp, msg=nil, &blk)
265
+ return if @is_press
266
+ raise "must send http request before assert!" if @response == nil
267
+ expect = find_attr xpath, attr, &blk
268
+ exp = /#{Regexp.escape(regexp)}/ if String === regexp
269
+ msg = "assert_no_attr xpath[#{xpath}] attr[#{attr}] regexp[#{regexp}] fail!" if msg.nil?
270
+ assert_no_match exp, expect, msg
271
+ $log.debug "assert_no_attr xpath[#{xpath}] attr[#{attr}] regexp[#{regexp}] success!"
272
+ end
273
+
274
+ # === 功能:
275
+ # 验证匹配的个数,如当前页某栏目的内容数
276
+ #
277
+ # === 参数解释:
278
+ # - xpath 定位,可以使xpath or selector
279
+ # - size 期待的结果,Fixnum
280
+ # - msg 失败之后的提示文字
281
+ #
282
+ # === Example:
283
+ # Example:
284
+ # get "http://hi.baidu.com/"
285
+ # assert_size "div#m_space ul li", 12
286
+ # # 百度空间首页,精彩空间栏会出12个推荐空间
287
+ def assert_size(xpath, size, msg=nil, &blk)
288
+ return if @is_press
289
+ raise "must send http request before assert!" if @response == nil
290
+ expect = find_size xpath, &blk
291
+ msg = "assert_size xpath[#{xpath}] size[#{size}] expect[#{expect}] fail!" if msg.nil?
292
+ assert expect == size, msg
293
+ $log.debug "assert_size xpath[#{xpath}] size[#{size}] expect[#{expect}] success!"
294
+ end
295
+
296
+ # === 功能:
297
+ # 验证某元素不含有非预计的儿子节点
298
+ #
299
+ # === 参数解释:
300
+ # - xpath 父亲节点的定位,可以使xpath or selector
301
+ # - children 预计的儿子节点名字的集合,如%w{title author body}
302
+ # - msg 失败之后的提示文字
303
+ #
304
+ # === Example:
305
+ # Example:
306
+ # get "http://hi.baidu.com/"
307
+ # assert_children "head", %w{title script link meta}
308
+ # #=> assert_children xpath[head] has children[["title", "script", "link", "meta"]], AND has other children[["style"]]!.
309
+ #
310
+ def assert_children(xpath, children, msg=nil, &blk)
311
+ return if @is_press
312
+ raise "must send http request before assert!" if @response == nil
313
+ expect = find_children xpath,children, &blk
314
+
315
+ msg = "assert_children xpath[#{xpath}] has children[#{children}], AND has other children[#{expect}]!" if msg.nil?
316
+ assert expect.empty?, msg
317
+ $log.debug "assert_children xpath[#{xpath}] children[#{children}] success!"
318
+ end
319
+
320
+ end
321
+
322
+
323
+ if __FILE__ == $0
324
+ class MyTest
325
+ include AssertHelper
326
+ include HttpHelper
327
+
328
+ def initialize
329
+ @cookies = {}
330
+ end
331
+
332
+ def test
333
+ get "http://www.baidu.com/"
334
+ doc = Hpricot(@response.body)
335
+ s = doc.search("div#u")
336
+ p s
337
+ puts s.html
338
+ puts s.attr("id")
339
+ end
340
+ end
341
+ Test.new.test
342
+ end
343
+
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ #
4
+ # Author:: hanyu
5
+ # Date:: 2009.9.6
6
+
7
+
8
+ # hack Hpricot
9
+ # 因为 Hpricot 将实体字符进行了反转义,这个过程存在很多的编码问题,解决起来不太容易,
10
+ # 而且这种反转义可能并不是我们需要的,所以去掉了
11
+ module Hpricot # :nodoc:
12
+ def self.uxs(str)
13
+ str.to_s.force_encoding("gbk")
14
+ #gsub(/\&(\w+);/){ [NamedCharacters[$1] || ??].pack("U*") }
15
+ #gsub(/\&\#(\d+);/){ [$1.to_i].pack("U*").encode("gbk") }.force_encoding("gbk")
16
+ end
17
+ end
18
+
19
+
20
+ # 基于hpricot (0.8.2)修改,如果版本发生变化,可能会有问题
21
+
22
+
23
+ # 尝试fix Hpricot在解析xpath的时候 对带冒号的字符串匹配有问题
24
+ # 可能会存在引入新bug的风险,对Hpricot的解析方式没有完全搞懂
25
+ module Hpricot
26
+ module Traverse
27
+ def search(expr, &blk)
28
+ if Range === expr
29
+ return Elements.expand(at(expr.begin), at(expr.end), expr.exclude_end?)
30
+ end
31
+ last = nil
32
+ nodes = [self]
33
+ done = []
34
+ expr = expr.to_s
35
+ hist = []
36
+ until expr.empty?
37
+ expr = clean_path(expr)
38
+ expr.gsub!(%r!^//!, '')
39
+
40
+ case expr
41
+ when %r!^/?\.\.!
42
+ last = expr = $'
43
+ nodes.map! { |node| node.parent }
44
+ when %r!^[>/]\s*!
45
+ last = expr = $'
46
+ nodes = Elements[*nodes.map { |node| node.children if node.respond_to? :children }.flatten.compact]
47
+ when %r!^\+!
48
+ last = expr = $'
49
+ nodes.map! do |node|
50
+ siblings = node.parent.children
51
+ siblings[siblings.index(node)+1]
52
+ end
53
+ nodes.compact!
54
+ when %r!^~!
55
+ last = expr = $'
56
+ nodes.map! do |node|
57
+ siblings = node.parent.children
58
+ siblings[(siblings.index(node)+1)..-1]
59
+ end
60
+ nodes.flatten!
61
+ when %r!^[|,]!
62
+ last = expr = " #$'"
63
+ nodes.shift if nodes.first == self
64
+ done += nodes
65
+ nodes = [self]
66
+ else
67
+ #puts "++++++++++++++++"
68
+ #p expr
69
+ m = expr.match(%r!^([#.]?)([a-z0-9\\*_-]*)!i).to_a
70
+ #p m
71
+ after = $'
72
+ #p after
73
+ #mt = after[%r!:[a-z0-9\\*_-]+!i, 0]
74
+ mt = after[%r!^:[a-z0-9\\*_-]+!i, 0]
75
+ #p mt
76
+ oop = false
77
+ if mt and not (mt == ":not" or Traverse.method_defined? "filter[#{mt}]")
78
+ after = $'
79
+ m[2] += mt
80
+ expr = after
81
+ end
82
+ if m[1] == '#'
83
+ oid = get_element_by_id(m[2])
84
+ nodes = oid ? [oid] : []
85
+ expr = after
86
+ else
87
+ m[2] = "*" if after =~ /^\(\)/ || m[2] == "" || m[1] == "."
88
+ ret = []
89
+ nodes.each do |node|
90
+ case m[2]
91
+ when '*'
92
+ node.traverse_element { |n| ret << n }
93
+ else
94
+ if node.respond_to? :get_elements_by_tag_name
95
+ ret += [*node.get_elements_by_tag_name(m[2])] - [*(node unless last)]
96
+ end
97
+ end
98
+ end
99
+ nodes = ret
100
+ end
101
+ last = nil
102
+ end
103
+
104
+ hist << expr
105
+ break if hist[-1] == hist[-2]
106
+ nodes, expr = Elements.filter(nodes, expr)
107
+ end
108
+ nodes = done + nodes.flatten.uniq
109
+ if blk
110
+ nodes.each(&blk)
111
+ self
112
+ else
113
+ Elements[*nodes]
114
+ end
115
+ end
116
+ end
117
+ end
118
+