super-test 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
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
+