firewatir 1.6.5 → 1.6.6.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/CHANGES +461 -0
  2. data/LICENSE +31 -31
  3. data/README.rdoc +112 -0
  4. data/VERSION +1 -0
  5. data/lib/firewatir.rb +41 -40
  6. data/lib/firewatir/container.rb +491 -491
  7. data/lib/firewatir/document.rb +239 -239
  8. data/lib/firewatir/element.rb +1364 -1364
  9. data/lib/firewatir/element_collections.rb +314 -314
  10. data/lib/firewatir/elements/button.rb +15 -15
  11. data/lib/firewatir/elements/file_field.rb +29 -29
  12. data/lib/firewatir/elements/form.rb +40 -40
  13. data/lib/firewatir/elements/frame.rb +55 -55
  14. data/lib/firewatir/elements/hidden.rb +56 -56
  15. data/lib/firewatir/elements/image.rb +139 -139
  16. data/lib/firewatir/elements/input_element.rb +44 -44
  17. data/lib/firewatir/elements/link.rb +76 -76
  18. data/lib/firewatir/elements/non_control_element.rb +53 -53
  19. data/lib/firewatir/elements/non_control_elements.rb +108 -108
  20. data/lib/firewatir/elements/not_used.rb +278 -278
  21. data/lib/firewatir/elements/option.rb +130 -130
  22. data/lib/firewatir/elements/radio_check_common.rb +163 -163
  23. data/lib/firewatir/elements/select_list.rb +188 -188
  24. data/lib/firewatir/elements/table.rb +218 -218
  25. data/lib/firewatir/elements/table_cell.rb +54 -54
  26. data/lib/firewatir/elements/table_row.rb +100 -100
  27. data/lib/firewatir/elements/text_field.rb +218 -218
  28. data/lib/firewatir/exceptions.rb +10 -10
  29. data/lib/firewatir/firefox.rb +984 -1040
  30. data/lib/firewatir/jssh_socket.rb +100 -100
  31. data/lib/firewatir/winClicker.rb +122 -122
  32. data/lib/firewatir/x11.rb +192 -192
  33. data/rakefile.rb +15 -0
  34. data/unittests/attach_to_new_window_test.rb +49 -49
  35. data/unittests/bug_fixes_test.rb +195 -195
  36. data/unittests/buttons_xpath_test.rb +88 -88
  37. data/unittests/checkbox_test.rb +158 -158
  38. data/unittests/checkbox_xpath_test.rb +107 -107
  39. data/unittests/div_test.rb +275 -275
  40. data/unittests/ff_test.rb +47 -0
  41. data/unittests/filefield_test.rb +49 -49
  42. data/unittests/filefield_xpath_test.rb +35 -35
  43. data/unittests/form_test.rb +296 -296
  44. data/unittests/frame_test.rb +159 -159
  45. data/unittests/hidden_test.rb +85 -85
  46. data/unittests/hidden_xpath_test.rb +72 -72
  47. data/unittests/html/JavascriptClick.html +42 -42
  48. data/unittests/html/blankpage.html +11 -11
  49. data/unittests/html/buttons1.html +61 -61
  50. data/unittests/html/checkboxes1.html +70 -70
  51. data/unittests/html/complex_table.html +36 -36
  52. data/unittests/html/cssTest.html +42 -42
  53. data/unittests/html/div.html +72 -72
  54. data/unittests/html/div_xml.html +20 -20
  55. data/unittests/html/fileupload.html +45 -45
  56. data/unittests/html/formTest1.html +38 -38
  57. data/unittests/html/forms2.html +45 -45
  58. data/unittests/html/forms3.html +132 -132
  59. data/unittests/html/forms4.html +27 -27
  60. data/unittests/html/frame_buttons.html +3 -3
  61. data/unittests/html/frame_links.html +3 -3
  62. data/unittests/html/frame_multi.html +4 -4
  63. data/unittests/html/iframeTest.html +14 -14
  64. data/unittests/html/iframeTest1.html +13 -13
  65. data/unittests/html/iframeTest2.html +5 -5
  66. data/unittests/html/images1.html +66 -66
  67. data/unittests/html/javascriptevents.html +35 -35
  68. data/unittests/html/link_pass.html +10 -10
  69. data/unittests/html/links1.html +42 -42
  70. data/unittests/html/links2.html +10 -10
  71. data/unittests/html/modal_dialog.html +8 -8
  72. data/unittests/html/modal_dialog_launcher.html +11 -11
  73. data/unittests/html/nestedFrames.html +6 -6
  74. data/unittests/html/new_browser.html +17 -17
  75. data/unittests/html/new_browser_popup.html +7 -7
  76. data/unittests/html/pass.html +9 -9
  77. data/unittests/html/popups1.html +60 -60
  78. data/unittests/html/pre.html +27 -27
  79. data/unittests/html/radioButtons1.html +70 -70
  80. data/unittests/html/redirect.html +10 -10
  81. data/unittests/html/redirect1.html +8 -8
  82. data/unittests/html/redirect2.html +8 -8
  83. data/unittests/html/redirect3.html +8 -8
  84. data/unittests/html/select_tealeaf.html +54 -54
  85. data/unittests/html/selectboxes1.html +55 -55
  86. data/unittests/html/simple_table.html +26 -26
  87. data/unittests/html/simple_table_buttons.html +104 -104
  88. data/unittests/html/simple_table_columns.html +74 -74
  89. data/unittests/html/table1.html +165 -165
  90. data/unittests/html/tableCell_using_xpath.html +19 -19
  91. data/unittests/html/textarea.html +30 -30
  92. data/unittests/html/textfields1.html +62 -62
  93. data/unittests/html/textsearch.html +44 -44
  94. data/unittests/images_test.rb +198 -198
  95. data/unittests/images_xpath_test.rb +118 -118
  96. data/unittests/javascript_test.rb +75 -75
  97. data/unittests/links_test.rb +231 -231
  98. data/unittests/links_xpath_test.rb +79 -79
  99. data/unittests/mozilla_all_tests.rb +7 -7
  100. data/unittests/pre_test.rb +75 -75
  101. data/unittests/radios_test.rb +166 -166
  102. data/unittests/radios_xpath_test.rb +101 -101
  103. data/unittests/redirect_test.rb +41 -41
  104. data/unittests/selectbox_test.rb +142 -142
  105. data/unittests/selectbox_xpath_test.rb +129 -129
  106. data/unittests/setup.rb +29 -29
  107. data/unittests/table_test.rb +385 -385
  108. data/unittests/table_xpath_test.rb +185 -185
  109. data/unittests/textfields_test.rb +234 -234
  110. data/unittests/textfields_xpath_test.rb +113 -113
  111. metadata +51 -19
  112. data/lib/firewatir/version.rb +0 -5
@@ -1,1365 +1,1365 @@
1
- module FireWatir
2
- # Base class for html elements.
3
- # This is not a class that users would normally access.
4
- class Element
5
- include FireWatir::Container
6
- # Number of spaces that separate the property from the value in the to_s method
7
- TO_S_SIZE = 14
8
-
9
- # How to get the nodes using XPath in mozilla.
10
- ORDERED_NODE_ITERATOR_TYPE = 5
11
- # To get the number of nodes returned by the xpath expression
12
- NUMBER_TYPE = 1
13
- # To get single node value
14
- FIRST_ORDERED_NODE_TYPE = 9
15
- # This stores the level to which we have gone finding element inside another element.
16
- # This is just to make sure that every element has unique name in JSSH.
17
- @@current_level = 0
18
- # This stores the name of the element that is about to trigger an Javascript pop up.
19
- #@@current_js_object = nil
20
-
21
- attr_accessor :element_name
22
- #
23
- # Description:
24
- # Creates new instance of element. If argument is not nil and is of type string this
25
- # sets the element_name and element_type property of the object. These properties can
26
- # be accessed using element_object and element_type methods respectively.
27
- #
28
- # Used internally by FireWatir.
29
- #
30
- # Input:
31
- # element - Name of the variable with which the element is referenced in JSSh.
32
- #
33
- def initialize(element, container=nil)
34
- @container = container
35
- @element_name = element
36
- @element_type = element_type
37
- #puts "in initialize "
38
- #puts caller(0)
39
- #if(element != nil && element.class == String)
40
- #@element_name = element
41
- #elsif(element != nil && element.class == Element)
42
- # @o = element
43
- #end
44
-
45
- #puts "@element_name is #{@element_name}"
46
- #puts "@element_type is #{@element_type}"
47
- end
48
-
49
- private
50
- def self.def_wrap(ruby_method_name, ole_method_name = nil)
51
- ole_method_name = ruby_method_name unless ole_method_name
52
- class_eval "def #{ruby_method_name}
53
- assert_exists
54
- # Every element has its name starting from element. If yes then
55
- # use element_name to send the command to jssh. Else its a number
56
- # and we are still searching for element, in this case use doc.all
57
- # array with element_name as index to send command to jssh
58
- #puts element_object.to_s
59
- #if(@element_type == 'HTMLDivElement')
60
- # ole_method_name = 'innerHTML'
61
- #end
62
- jssh_socket.send('typeof(' + element_object + '.#{ole_method_name});\n', 0)
63
- return_type = read_socket()
64
-
65
- return_value = get_attribute_value(\"#{ole_method_name}\")
66
-
67
- #if(return_value == '' || return_value == \"null\")
68
- # return_value = \"\"
69
- #end
70
-
71
- if(return_type == \"boolean\")
72
- return_value = false if return_value == \"false\"
73
- return_value = true if return_value == \"true\"
74
- end
75
- #puts return_value
76
- @@current_level = 0
77
- return return_value
78
- end"
79
- end
80
-
81
- def get_attribute_value(attribute_name)
82
- #if the attribut name is columnLength get number of cells in first row if rows exist.
83
- case attribute_name
84
- when "columnLength"
85
- rowsLength = js_eval_method "columns"
86
- if (rowsLength != 0 || rowsLength != "")
87
- return js_eval_method("rows[0].cells.length")
88
- end
89
- when "text"
90
- return text
91
- when "url", "href", "src", "action", "name"
92
- return_value = js_eval_method("getAttribute(\"#{attribute_name}\")")
93
- else
94
- jssh_command = "var attribute = '';
95
- if(#{element_object}.#{attribute_name} != undefined)
96
- attribute = #{element_object}.#{attribute_name};
97
- else
98
- attribute = #{element_object}.getAttribute(\"#{attribute_name}\");
99
- attribute;"
100
- return_value = js_eval(jssh_command)
101
- end
102
- if attribute_name == "value"
103
- tagName = js_eval_method("tagName").downcase
104
- type = js_eval_method("type").downcase
105
-
106
- if tagName == "button" || ["image", "submit", "reset", "button"].include?(type)
107
- if return_value == "" || return_value == "null"
108
- return_value = js_eval_method "innerHTML"
109
- end
110
- end
111
- end
112
-
113
- if return_value == "null" || return_value =~ /\[object\s.*\]/
114
- return_value = ""
115
- end
116
- return return_value
117
- end
118
- private :get_attribute_value
119
-
120
-
121
- #
122
- # Description:
123
- # Returns an array of the properties of an element, in a format to be used by the to_s method.
124
- # additional attributes are returned based on the supplied atributes hash.
125
- # name, type, id, value and disabled attributes are common to all the elements.
126
- # This method is used internally by to_s method.
127
- #
128
- # Output:
129
- # Array with values of the following properties:
130
- # name, type, id, value disabled and the supplied attribues list.
131
- #
132
- def string_creator(attributes = nil)
133
- n = []
134
- n << "name:".ljust(TO_S_SIZE) + get_attribute_value("name")
135
- n << "type:".ljust(TO_S_SIZE) + get_attribute_value("type")
136
- n << "id:".ljust(TO_S_SIZE) + get_attribute_value("id")
137
- n << "value:".ljust(TO_S_SIZE) + get_attribute_value("value")
138
- n << "disabled:".ljust(TO_S_SIZE) + get_attribute_value("disabled")
139
- #n << "style:".ljust(TO_S_SIZE) + get_attribute_value("style")
140
- #n << "class:".ljust(TO_S_SIZE) + get_attribute_value("className")
141
-
142
- if(attributes != nil)
143
- attributes.each do |key,value|
144
- n << "#{key}:".ljust(TO_S_SIZE) + get_attribute_value(value)
145
- end
146
- end
147
- return n
148
- end
149
-
150
- #
151
- # Description:
152
- # Sets and clears the colored highlighting on the currently active element.
153
- #
154
- # Input:
155
- # set_or_clear - this can have following two values
156
- # :set - To set the color of the element.
157
- # :clear - To clear the color of the element.
158
- #
159
- def highlight(set_or_clear)
160
- if set_or_clear == :set
161
- #puts "element_name is : #{element_object}"
162
- jssh_command = " var original_color = #{element_object}.style.background;"
163
- jssh_command << " #{element_object}.style.background = \"#{DEFAULT_HIGHLIGHT_COLOR}\"; original_color;"
164
-
165
- # TODO: Need to change this so that it would work if user sets any other color.
166
- #puts "color is : #{DEFAULT_HIGHLIGHT_COLOR}"
167
- jssh_socket.send("#{jssh_command}\n", 0)
168
- @original_color = read_socket()
169
-
170
- else # BUG: assumes is :clear, but could actually be anything
171
- begin
172
- jssh_socket.send("#{element_object}.style.background = \"#{@original_color}\";\n", 0)
173
- read_socket()
174
- rescue
175
- # we could be here for a number of reasons...
176
- # e.g. page may have reloaded and the reference is no longer valid
177
- ensure
178
- @original_color = nil
179
- end
180
- end
181
- end
182
- protected :highlight
183
-
184
- #
185
- # Description:
186
- # Returns array of rows for a given table. Returns nil if calling element is not of table type.
187
- #
188
- # Output:
189
- # Array of row elements in an table or nil
190
- #
191
- def get_rows()
192
- #puts "#{element_object} and #{element_type}"
193
- if(element_type == "HTMLTableElement")
194
- jssh_socket.send("#{element_object}.rows.length;\n", 0)
195
- length = read_socket().to_i
196
- #puts "The number of rows in the table are : #{no_of_rows}"
197
- return_array = Array.new(length)
198
- for i in 0..length - 1 do
199
- return_array[i] = "#{element_object}.rows[#{i}]"
200
- end
201
- return return_array
202
- else
203
- puts "Trying to access rows for Element of type #{element_type}. Element must be of table type to execute this function."
204
- return nil
205
- end
206
- end
207
- private :get_rows
208
-
209
- def set_specifier(how, what)
210
- if how.class == Hash and what.nil?
211
- specifiers = how
212
- else
213
- specifiers = {how => what}
214
- end
215
-
216
- @specifiers = {:index => 1} # default if not specified
217
-
218
- specifiers.each do |how, what|
219
- what = what.to_i if how == :index
220
- how = :href if how == :url
221
- how = :value if how == :caption
222
- how = :class if how == :class_name
223
-
224
- @specifiers[how] = what
225
- end
226
- end
227
-
228
- #
229
- # Description:
230
- # Locates the element on the page depending upon the parameters passed. Logic for locating the element is written
231
- # in JavaScript and then send to JSSh; so that we don't make small round-trips via socket to JSSh. This is done to
232
- # improve the performance for locating the element.
233
- #
234
- # Input:
235
- # tag - Tag name of the element to be located like "input", "a" etc. This is case insensitive.
236
- # how - The attribute by which you want to locate the element like id, name etc. You can use any attribute-value pair
237
- # that uniquely identifies that element on the page. If there are more that one element that have identical
238
- # attribute-value pair then first element that is found while traversing the DOM will be returned.
239
- # what - The value of the attribute specified by how.
240
- # types - Used if that HTML element to be located has different type like input can be of type image, button etc.
241
- # Default value is nil
242
- # value - This is used only in case of radio buttons where they have same name but different value.
243
- #
244
- # Output:
245
- # Returns nil if unable to locate the element, else return the element.
246
- #
247
- def locate_tagged_element(tag, how, what, types = nil, value = nil)
248
- #puts caller(0)
249
- # how = :value if how == :caption
250
- # how = :href if how == :url
251
- set_specifier(how, what)
252
- #puts "(locate_tagged_element)current element is : #{@container.class} and tag is #{tag}"
253
- # If there is no current element i.e. element in current context we are searching the whole DOM tree.
254
- # So get all the elements.
255
-
256
- if(types != nil and types.include?("button"))
257
- jssh_command = "var isButtonElement = true;"
258
- else
259
- jssh_command = "var isButtonElement = false;"
260
- end
261
-
262
- # Because in both the below cases we need to get element with respect to document.
263
- # when we locate a frame document is automatically adjusted to point to HTML inside the frame
264
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
265
- #end
266
- #if(@@current_element_object == "")
267
- jssh_command << "var elements_#{tag} = null; elements_#{tag} = #{@container.document_var}.getElementsByTagName(\"#{tag}\");"
268
- if(types != nil and (types.include?("textarea") or types.include?("button")) )
269
- jssh_command << "elements_#{tag} = #{@container.document_var}.body.getElementsByTagName(\"*\");"
270
- end
271
- # @@has_changed = true
272
- else
273
- #puts "container name is: " + @container.element_name
274
- #locate if defined? locate
275
- #@container.locate
276
- jssh_command << "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
277
- if(types != nil and (types.include?("textarea") or types.include?("button") ) )
278
- jssh_command << "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
279
- end
280
- # @@has_changed = false
281
- end
282
-
283
-
284
- if(types != nil)
285
- jssh_command << "var types = new Array("
286
- count = 0
287
- types.each do |type|
288
- if count == 0
289
- jssh_command << "\"#{type}\""
290
- count += 1
291
- else
292
- jssh_command << ",\"#{type}\""
293
- end
294
- end
295
- jssh_command << ");"
296
- else
297
- jssh_command << "var types = null;"
298
- end
299
- #jssh_command << "var elements = #{element_object}.getElementsByTagName('*');"
300
- jssh_command << "var object_index = 1; var o = null; var element_name = \"\";"
301
-
302
- case value
303
- when Regexp
304
- jssh_command << "var value = #{ rb_regexp_to_js(value) };"
305
- when nil
306
- jssh_command << "var value = null;"
307
- else
308
- jssh_command << "var value = \"#{value}\";"
309
- end
310
-
311
- #add hash arrays
312
- sKey = "var hashKeys = new Array("
313
- sVal = "var hashValues = new Array("
314
- @specifiers.each do |k,v|
315
- sKey += "\"#{k}\","
316
- if v.is_a?(Regexp)
317
- sVal += "#{rb_regexp_to_js(v)},"
318
- else
319
- sVal += "\"#{v}\","
320
- end
321
- end
322
- sKey = sKey[0..sKey.length-2]
323
- sVal = sVal[0..sVal.length-2]
324
- jssh_command << sKey + ");"
325
- jssh_command << sVal + ");"
326
-
327
- #index
328
- jssh_command << "var target_index = 1;
329
- for(var k=0; k<hashKeys.length; k++)
330
- {
331
- if(hashKeys[k] == \"index\")
332
- {
333
- target_index = parseInt(hashValues[k]);
334
- break;
335
- }
336
- }"
337
-
338
- #jssh_command << "elements.length;"
339
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
340
-
341
- jssh_command << "for(var i=0; i<elements_#{tag}.length; i++)
342
- {
343
- if(element_name != \"\") break;
344
- var element = elements_#{tag}[i];"
345
- else
346
- jssh_command << "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
347
- {
348
- if(element_name != \"\") break;
349
- var element = elements_#{@@current_level}_#{tag}[i];"
350
- end
351
-
352
- # Because in IE for button the value of "value" attribute also corresponds to the innerHTML if value attribute
353
- # is not supplied. For e.g.: <button>Sign In</button>, in this case value of "value" attribute is "Sign In"
354
- # though value attribute is not supplied. But for Firefox value of "value" attribute is null. So to make sure
355
- # script runs on both IE and Watir we are also considering innerHTML if element is of button type.
356
- jssh_command << " var attribute = \"\";
357
- var same_type = false;
358
- if(types)
359
- {
360
- for(var j=0; j<types.length; j++)
361
- {
362
- if(types[j] == element.type || types[j] == element.tagName)
363
- {
364
- same_type = true;
365
- break;
366
- }
367
- }
368
- }
369
- else
370
- {
371
- same_type = true;
372
- }
373
- if(same_type == true)
374
- {
375
- var how = \"\";
376
- var what = null;
377
- attribute = \"\";
378
- for(var k=0; k<hashKeys.length; k++)
379
- {
380
- how = hashKeys[k];
381
- what = hashValues[k];
382
-
383
- if(how == \"index\")
384
- {
385
- attribute = parseInt(what);
386
- what = parseInt(what);
387
- }
388
- else
389
- {
390
- if(how == \"text\")
391
- {
392
- attribute = element.textContent.replace(/\\xA0/g,' ').replace(/^\\s+|\\s+$/g, '').replace(/\\s+/g, ' ')
393
- }
394
- else
395
- {
396
- if(how == \"href\" || how == \"src\" || how == \"action\" || how == \"name\")
397
- {
398
- attribute = element.getAttribute(how);
399
- }
400
- else
401
- {
402
- if(eval(\"element.\"+how) != undefined)
403
- attribute = eval(\"element.\"+how);
404
- else
405
- attribute = element.getAttribute(how);
406
- }
407
- }
408
- if(\"value\" == how && isButtonElement && (attribute == null || attribute == \"\"))
409
- {
410
- attribute = element.innerHTML;
411
- }
412
- }
413
- if(attribute == \"\") o = 'NoMethodError';
414
- var found = false;
415
- if (typeof what == \"object\" || typeof what == \"function\")
416
- {
417
- var regExp = new RegExp(what);
418
- found = regExp.test(attribute);
419
- }
420
- else
421
- {
422
- found = (attribute == what);
423
- }"
424
-
425
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
426
- jssh_command << " if(found)
427
- {
428
- if(value)
429
- {
430
- if(element.value == value || (value.test && value.test(element.value)))
431
- {
432
- o = element;
433
- element_name = \"elements_#{tag}[\" + i + \"]\";
434
- }
435
- else
436
- break;
437
- }
438
- else
439
- {
440
- o = element;
441
- element_name = \"elements_#{tag}[\" + i + \"]\";
442
- }
443
- }"
444
- else
445
- jssh_command << " if(found)
446
- {
447
- if(value)
448
- {
449
- if(element.value == value || (value.test && value.test(element.value)))
450
- {
451
- o = element;
452
- element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
453
- }
454
- else
455
- break;
456
- }
457
- else
458
- {
459
- o = element;
460
- element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
461
- }
462
- }"
463
- end
464
-
465
- jssh_command << "
466
- else {
467
- o = null;
468
- element_name = \"\";
469
- break;
470
- }
471
- }
472
- if(element_name != \"\")
473
- {
474
- if(target_index == object_index)
475
- {
476
- break;
477
- }
478
- else if(target_index < object_index)
479
- {
480
- element_name = \"\";
481
- o = null;
482
- break;
483
- }
484
- else
485
- {
486
- object_index += 1;
487
- element_name = \"\";
488
- o = null;
489
- }
490
- }
491
- }
492
- }
493
- element_name;"
494
-
495
- # Remove \n that are there in the string as a result of pressing enter while formatting.
496
- jssh_command.gsub!(/\n/, "")
497
- #puts jssh_command
498
- #out = File.new("c:\\result.log", "w")
499
- #out << jssh_command
500
- #out.close
501
- jssh_socket.send("#{jssh_command};\n", 0)
502
- element_name = read_socket();
503
- #puts "element name in find control is : #{element_name}"
504
- @@current_level = @@current_level + 1
505
- #puts @container
506
- #puts element_name
507
- if(element_name != "")
508
- return element_name #Element.new(element_name, @container)
509
- else
510
- return nil
511
- end
512
- end
513
-
514
- def rb_regexp_to_js(regexp)
515
- old_exp = regexp.to_s
516
- new_exp = regexp.inspect.sub(/\w*$/, '')
517
- flags = old_exp.slice(2, old_exp.index(':') - 2)
518
-
519
- for i in 0..flags.length do
520
- flag = flags[i, 1]
521
- if(flag == '-')
522
- break;
523
- else
524
- new_exp << flag
525
- end
526
- end
527
-
528
- new_exp
529
- end
530
-
531
- #
532
- # Description:
533
- # Locates frame element. Logic for locating the frame is written in JavaScript so that we don't make small
534
- # round trips to JSSh using socket. This is done to improve the performance for locating the element.
535
- #
536
- # Input:
537
- # how - The attribute for locating the frame. You can use any attribute-value pair that uniquely identifies
538
- # the frame on the page. If there are more than one frames that have identical attribute-value pair
539
- # then first frame that is found while traversing the DOM will be returned.
540
- # what - Value of the attribute specified by how
541
- #
542
- # Output:
543
- # Nil if unable to locate frame, else return the Frame element.
544
- #
545
- # TODO/FIX: If multiple tabs are open on the current window, will count frames from every tab, not just the current tab.
546
- #
547
- def locate_frame(how, what)
548
- # Get all the frames the are there on the page.
549
- #puts "how is #{how} and what is #{what}"
550
- jssh_command = ""
551
- if(@container.class == FireWatir::Firefox)
552
- # In firefox 3 if you write Frame Name then it will not show anything. So we add .toString function to every element.
553
- jssh_command = "var frameset = #{@container.window_var}.frames;
554
- var elements_frames = new Array();
555
- for(var i = 0; i < frameset.length; i++)
556
- {
557
- var frames = frameset[i].frames;
558
- for(var j = 0; j < frames.length; j++)
559
- {
560
- frames[j].frameElement.toString = function() { return '[object HTMLFrameElement]'; };
561
- elements_frames.push(frames[j].frameElement);
562
-
563
- }
564
- }"
565
- else
566
- jssh_command = "var frames = #{@container.element_name}.contentWindow.frames;
567
- var elements_frames_#{@@current_level} = new Array();
568
- for(var i = 0; i < frames.length; i++)
569
- {
570
- elements_frames_#{@@current_level}.push(frames[i].frameElement);
571
- }"
572
- end
573
-
574
- jssh_command << " var element_name = ''; var object_index = 1;var attribute = '';
575
- var element = '';"
576
- if(@container.class == FireWatir::Firefox)
577
- jssh_command << "for(var i = 0; i < elements_frames.length; i++)
578
- {
579
- element = elements_frames[i];"
580
- else
581
- jssh_command << "for(var i = 0; i < elements_frames_#{@@current_level}.length; i++)
582
- {
583
- element = elements_frames_#{@@current_level}[i];"
584
- end
585
- jssh_command << " if(\"index\" == \"#{how}\")
586
- {
587
- attribute = object_index; object_index += 1;
588
- }
589
- else
590
- {
591
- attribute = element.getAttribute(\"#{how}\");
592
- if(attribute == \"\" || attribute == null)
593
- {
594
- attribute = element.#{how};
595
- }
596
- }
597
- var found = false;"
598
- if(what.class == Regexp)
599
- oldRegExp = what.to_s
600
- newRegExp = "/" + what.source + "/"
601
- flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
602
-
603
- for i in 0..flags.length do
604
- flag = flags[i, 1]
605
- if(flag == '-')
606
- break;
607
- else
608
- newRegExp << flag
609
- end
610
- end
611
- #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
612
- jssh_command << " var regExp = new RegExp(#{newRegExp});
613
- found = regExp.test(attribute);"
614
- elsif(how == :index)
615
- jssh_command << " found = (attribute == #{what});"
616
- else
617
- jssh_command << " found = (attribute == \"#{what}\");"
618
- end
619
-
620
- jssh_command << " if(found)
621
- {"
622
- if(@container.class == FireWatir::Firefox)
623
- jssh_command << " element_name = \"elements_frames[\" + i + \"]\";
624
- #{@container.document_var} = elements_frames[i].contentDocument;
625
- #{@container.body_var} = #{@container.document_var}.body;"
626
- else
627
- jssh_command << " element_name = \"elements_frames_#{@@current_level}[\" + i + \"]\";
628
- #{@container.document_var} = elements_frames_#{@@current_level}[i].contentDocument;
629
- #{@container.body_var} = #{@container.document_var}.body;"
630
- end
631
- jssh_command << " break;
632
- }
633
- }
634
- element_name;"
635
-
636
- jssh_command.gsub!("\n", "")
637
- #puts "jssh_command for finding frame is : #{jssh_command}"
638
-
639
- jssh_socket.send("#{jssh_command};\n", 0)
640
- element_name = read_socket()
641
- @@current_level = @@current_level + 1
642
- #puts "element_name for frame is : #{element_name}"
643
-
644
- if(element_name != "")
645
- return element_name
646
- else
647
- return nil
648
- end
649
- end
650
-
651
- def get_frame_html
652
- jssh_socket.send("var htmlelem = #{@container.document_var}.getElementsByTagName('html')[0]; htmlelem.innerHTML;\n", 0)
653
- #jssh_socket.send("body.innerHTML;\n", 0)
654
- result = read_socket()
655
- return "<html>" + result + "</html>"
656
- end
657
-
658
- def submit_form
659
- #puts "form name is : #{element_object}"
660
- jssh_socket.send("#{element_object}.submit();\n" , 0)
661
- read_socket()
662
- end
663
-
664
- public
665
-
666
- #
667
- #
668
- # Description:
669
- # Matches the given text with the current text shown in the browser for that particular element.
670
- #
671
- # Input:
672
- # target - Text to match. Can be a string or regex
673
- #
674
- # Output:
675
- # Returns the index if the specified text was found.
676
- # Returns matchdata object if the specified regexp was found.
677
- #
678
- def contains_text(target)
679
- #puts "Text to match is : #{match_text}"
680
- #puts "Html is : #{self.text}"
681
- if target.kind_of? Regexp
682
- self.text.match(target)
683
- elsif target.kind_of? String
684
- self.text.index(target)
685
- else
686
- raise TypeError, "Argument #{target} should be a string or regexp."
687
- end
688
- end
689
-
690
-
691
- def inspect
692
- '#<%s:0x%x located=%s how=%s what=%s>' % [self.class, hash*2, !!@o, @how.inspect, @what.inspect]
693
- end
694
-
695
- #
696
- # Description:
697
- # Returns array of elements that matches a given XPath query.
698
- # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
699
- # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
700
- # Used internally by Firewatir use ff.elements_by_xpath instead.
701
- #
702
- # Input:
703
- # xpath - The xpath expression or query.
704
- #
705
- # Output:
706
- # Array of elements that matched the xpath expression provided as parameter.
707
- #
708
- def elements_by_xpath(container, xpath)
709
- rand_no = rand(1000)
710
- #jssh_command = "var xpathResult = document.evaluate(\"count(#{xpath})\", document, null, #{NUMBER_TYPE}, null); xpathResult.numberValue;"
711
- #jssh_socket.send("#{jssh_command}\n", 0);
712
- #node_count = read_socket()
713
- xpath.gsub!("\"", "\\\"")
714
- jssh_command = "var element_xpath_#{rand_no} = new Array();"
715
-
716
- jssh_command << "var result = #{@container.document_var}.evaluate(\"#{xpath}\", #{@container.document_var}, null, #{ORDERED_NODE_ITERATOR_TYPE}, null);
717
- var iterate = result.iterateNext();
718
- while(iterate)
719
- {
720
- element_xpath_#{rand_no}.push(iterate);
721
- iterate = result.iterateNext();
722
- }
723
- element_xpath_#{rand_no}.length;
724
- "
725
-
726
- # Remove \n that are there in the string as a result of pressing enter while formatting.
727
- jssh_command.gsub!(/\n/, "")
728
- #puts jssh_command
729
- jssh_socket.send("#{jssh_command};\n", 0)
730
- node_count = read_socket()
731
- #puts "value of count is : #{node_count}"
732
-
733
- elements = Array.new(node_count.to_i)
734
-
735
- for i in 0..elements.length - 1 do
736
- elements[i] = "element_xpath_#{rand_no}[#{i}]"
737
- end
738
-
739
- return elements;
740
- end
741
-
742
- #
743
- # Description:
744
- # Returns first element found while traversing the DOM; that matches an given XPath query.
745
- # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
746
- # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
747
- # Used internally by Firewatir use ff.element_by_xpath instead.
748
- #
749
- # Input:
750
- # xpath - The xpath expression or query.
751
- #
752
- # Output:
753
- # First element in DOM that matched the XPath expression or query.
754
- #
755
- def element_by_xpath(container, xpath)
756
- #puts "here locating element by xpath"
757
- rand_no = rand(1000)
758
- xpath.gsub!("\"", "\\\"")
759
- jssh_command = "var element_xpath_#{rand_no} = null; element_xpath_#{rand_no} = #{@container.document_var}.evaluate(\"#{xpath}\", #{container.document_var}, null, #{FIRST_ORDERED_NODE_TYPE}, null).singleNodeValue; element_xpath_#{rand_no};"
760
-
761
- jssh_socket.send("#{jssh_command}\n", 0)
762
- result = read_socket()
763
- #puts "command send to jssh is : #{jssh_command}"
764
- #puts "result is : #{result}"
765
- if(result == "null" || result == "" || result.include?("exception"))
766
- @@current_level = 0
767
- return nil
768
- else
769
- @@current_level += 1
770
- return "element_xpath_#{rand_no}"
771
- end
772
- end
773
-
774
- #
775
- # Description:
776
- # Returns the name of the element with which we can access it in JSSh.
777
- # Used internally by Firewatir to execute methods, set properties or return property value for the element.
778
- #
779
- # Output:
780
- # Name of the variable with which element is referenced in JSSh
781
- #
782
- def element_object
783
- #puts caller.join("\n")
784
- #puts "In element_object element name is : #{@element_name}"
785
- #puts "in element_object : #{@container.class}"
786
- #if(@container.class == FireWatir::Firefox)
787
- return @element_name #if @element_name != nil
788
- #else
789
- # return @container.element_name
790
- #end
791
- #return @o.element_name if @o != nil
792
- end
793
- private :element_object
794
-
795
- #
796
- # Description:
797
- # Returns the type of element. For e.g.: HTMLAnchorElement. used internally by Firewatir
798
- #
799
- # Output:
800
- # Type of the element.
801
- #
802
- def element_type
803
- #puts "in element_type object is : #{element_object}"
804
- # Get the type of the element.
805
- jssh_socket.send("#{element_object};\n", 0)
806
- temp = read_socket()
807
-
808
- #puts "#{element_object} and type is #{temp}"
809
- temp =~ /\[object\s(.*)\]/
810
- if $1
811
- return $1
812
- else
813
- # This is done because in JSSh if you write element name of anchor type
814
- # then it displays the link to which it navigates instead of displaying
815
- # object type. So above regex match will return nil
816
- return "HTMLAnchorElement"
817
- end
818
- end
819
- #private :element_type
820
-
821
- #
822
- # Description:
823
- # Fires the provided event for an element and by default waits for the action to get completed.
824
- #
825
- # Input:
826
- # event - Event to be fired like "onclick", "onchange" etc.
827
- # wait - Whether to wait for the action to get completed or not. By default its true.
828
- #
829
- # TODO: Provide ability to specify event parameters like keycode for key events, and click screen
830
- # coordinates for mouse events.
831
- def fire_event(event, wait = true)
832
- assert_exists()
833
- event = event.to_s # in case event was given as a symbol
834
-
835
- event = event.downcase
836
-
837
- event =~ /on(.*)/i
838
- event = $1 if $1
839
-
840
- # check if we've got an old-school on-event
841
- #jssh_socket.send("typeof(#{element_object}.#{event});\n", 0)
842
- #is_defined = read_socket()
843
-
844
- # info about event types harvested from:
845
- # http://www.howtocreate.co.uk/tutorials/javascript/domevents
846
- case event
847
- when 'abort', 'blur', 'change', 'error', 'focus', 'load', 'reset', 'resize',
848
- 'scroll', 'select', 'submit', 'unload'
849
- dom_event_type = 'HTMLEvents'
850
- dom_event_init = "initEvent(\"#{event}\", true, true)"
851
- when 'keydown', 'keypress', 'keyup'
852
- dom_event_type = 'KeyEvents'
853
- # Firefox has a proprietary initializer for keydown/keypress/keyup.
854
- # Args are as follows:
855
- # 'type', bubbles, cancelable, windowObject, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
856
- dom_event_init = "initKeyEvent(\"#{event}\", true, true, #{@container.window_var}, false, false, false, false, 0, 0)"
857
- when 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover',
858
- 'mouseup'
859
- dom_event_type = 'MouseEvents'
860
- # Args are as follows:
861
- # 'type', bubbles, cancelable, windowObject, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget
862
- dom_event_init = "initMouseEvent(\"#{event}\", true, true, #{@container.window_var}, 1, 0, 0, 0, 0, false, false, false, false, 0, null)"
863
- else
864
- dom_event_type = 'HTMLEvents'
865
- dom_event_init = "initEvents(\"#{event}\", true, true)"
866
- end
867
-
868
- if(element_type == "HTMLSelectElement")
869
- dom_event_type = 'HTMLEvents'
870
- dom_event_init = "initEvent(\"#{event}\", true, true)"
871
- end
872
-
873
-
874
- jssh_command = "var event = #{@container.document_var}.createEvent(\"#{dom_event_type}\"); "
875
- jssh_command << "event.#{dom_event_init}; "
876
- jssh_command << "#{element_object}.dispatchEvent(event);"
877
-
878
- #puts "JSSH COMMAND:\n#{jssh_command}\n"
879
-
880
- jssh_socket.send("#{jssh_command}\n", 0)
881
- read_socket() if wait
882
- wait() if wait
883
-
884
- @@current_level = 0
885
- end
886
- alias fireEvent fire_event
887
-
888
- #
889
- # Description:
890
- # Returns the value of the specified attribute of an element.
891
- #
892
- def attribute_value(attribute_name)
893
- #puts attribute_name
894
- assert_exists()
895
- return_value = get_attribute_value(attribute_name)
896
- @@current_level = 0
897
- return return_value
898
- end
899
-
900
- #
901
- # Description:
902
- # Checks if element exists or not. Raises UnknownObjectException if element doesn't exists.
903
- #
904
- def assert_exists
905
- unless exists?
906
- raise UnknownObjectException.new(
907
- Watir::Exception.message_for_unable_to_locate(@how, @what))
908
- end
909
- end
910
-
911
- #
912
- # Description:
913
- # Checks if element is enabled or not. Raises ObjectDisabledException if object is disabled and
914
- # you are trying to use the object.
915
- #
916
- def assert_enabled
917
- unless enabled?
918
- raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
919
- end
920
- end
921
-
922
- #
923
- # Description:
924
- # First checks if element exists or not. Then checks if element is enabled or not.
925
- #
926
- # Output:
927
- # Returns true if element exists and is enabled, else returns false.
928
- #
929
- def enabled?
930
- assert_exists
931
- value = js_eval_method "disabled"
932
- @@current_level = 0
933
- return true if(value == "false")
934
- return false if(value == "true")
935
- return value
936
- end
937
-
938
- #
939
- # Description:
940
- # Checks element for display: none or visibility: hidden, these are
941
- # the most common methods to hide an html element
942
-
943
- def visible?
944
- assert_exists
945
- val = js_eval "var val = 'true'; var str = ''; var obj = #{element_object}; while (obj != null) { try { str = #{@container.document_var}.defaultView.getComputedStyle(obj,null).visibility; if (str=='hidden') { val = 'false'; break; } str = #{@container.document_var}.defaultView.getComputedStyle(obj,null).display; if (str=='none') { val = 'false'; break; } } catch(err) {} obj = obj.parentNode; } val;"
946
- return (val == 'false')? false: true
947
- end
948
-
949
-
950
- #
951
- # Description:
952
- # Checks if element exists or not. If element is not located yet then first locates the element.
953
- #
954
- # Output:
955
- # True if element exists, false otherwise.
956
- #
957
- def exists?
958
- # puts "element is : #{element_object}"
959
- # puts caller(0)
960
- # If elements array has changed locate the element again. So that the element name points to correct element.
961
- if(element_object == nil || element_object == "")
962
- @@current_level = 0
963
- #puts "locating element"
964
- locate if respond_to?(:locate)
965
- if(@element_name == nil || @element_name == "")
966
- return false
967
- else
968
- #puts caller(0)
969
- #puts "element name is : #{@element_name}"
970
- return true
971
- end
972
- else
973
- #puts "not locating the element again"
974
- return true
975
- end
976
- #@@current_level = 0
977
- #if(element_object == nil || element_object == "")
978
- # return false
979
- #else
980
- # return true
981
- #end
982
- rescue UnknownFrameException
983
- false
984
- end
985
- alias exist? exists?
986
-
987
- #
988
- # Description:
989
- # Returns the text of the element.
990
- #
991
- # Output:
992
- # Text of the element.
993
- #
994
- def text()
995
- assert_exists
996
- element = (element_type == "HTMLFrameElement") ? "body" : element_object
997
- return_value = js_eval("#{element}.textContent.replace(/\\xA0/g, ' ').replace(/\\s+/g, ' ')").strip
998
- @@current_level = 0
999
- return return_value
1000
- end
1001
- alias innerText text
1002
-
1003
- # Returns the name of the element (as defined in html)
1004
- def_wrap :name
1005
- # Returns the id of the element
1006
- def_wrap :id
1007
- # Returns whether the element is disabled
1008
- def disabled
1009
- ! enabled?
1010
- end
1011
- alias disabled? disabled
1012
- # Returns the state of the element
1013
- def_wrap :checked
1014
- # Returns the value of the element
1015
- def_wrap :value
1016
- # Returns the title of the element
1017
- def_wrap :title
1018
- # Returns the value of 'alt' attribute in case of Image element.
1019
- def_wrap :alt
1020
- # Returns the value of 'href' attribute in case of Anchor element.
1021
- def_wrap :src
1022
- # Returns the type of the element. Use in case of Input element only.
1023
- def_wrap :type
1024
- # Returns the url the Anchor element points to.
1025
- def_wrap :href
1026
- # Return the ID of the control that this label is associated with
1027
- def_wrap :for, :htmlFor
1028
- # Returns the class name of the element
1029
- def_wrap :class_name, :className
1030
- # Return the html of the object
1031
- def_wrap :html, :innerHTML
1032
- # Return the action of form
1033
- def_wrap :action
1034
-
1035
- #
1036
- # Description:
1037
- # Display basic details about the object. Sample output for a button is shown.
1038
- # Raises UnknownObjectException if the object is not found.
1039
- # name b4
1040
- # type button
1041
- # id b5
1042
- # value Disabled Button
1043
- # disabled true
1044
- #
1045
- # Output:
1046
- # Array with value of properties shown above.
1047
- #
1048
- def to_s(attributes=nil)
1049
- #puts "here in to_s"
1050
- #puts caller(0)
1051
- assert_exists
1052
- if(element_type == "HTMLTableCellElement")
1053
- return text()
1054
- else
1055
- result = string_creator(attributes).join("\n")
1056
- @@current_level = 0
1057
- return result
1058
- end
1059
- end
1060
-
1061
- #
1062
- # Description:
1063
- # Function to fire click event on elements.
1064
- #
1065
- def click
1066
- assert_exists
1067
- assert_enabled
1068
-
1069
- highlight(:set)
1070
- #puts "#{element_object} and #{element_type}"
1071
- case element_type
1072
-
1073
- when "HTMLAnchorElement", "HTMLImageElement"
1074
- # Special check for link or anchor tag. Because click() doesn't work on links.
1075
- # More info: http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-48250443
1076
- # https://bugzilla.mozilla.org/show_bug.cgi?id=148585
1077
-
1078
- jssh_command = "var event = #{@container.document_var}.createEvent(\"MouseEvents\");"
1079
-
1080
- # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1081
- jssh_command << "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1082
- jssh_command << "#{element_object}.dispatchEvent(event);\n"
1083
-
1084
- #puts "jssh_command is: #{jssh_command}"
1085
- jssh_socket.send("#{jssh_command}", 0)
1086
- read_socket()
1087
- else
1088
- jssh_socket.send("typeof(#{element_object}.click);\n", 0)
1089
- isDefined = read_socket()
1090
- if(isDefined == "undefined")
1091
- fire_event("onclick")
1092
- else
1093
- jssh_socket.send("#{element_object}.click();\n" , 0)
1094
- read_socket()
1095
- end
1096
- end
1097
- highlight(:clear)
1098
- # Wait for firefox to reload.
1099
- wait()
1100
- end
1101
-
1102
- #
1103
- # Description:
1104
- # Document var. Unfinished.
1105
- #
1106
- def document_var
1107
- "document"
1108
- end
1109
-
1110
- #
1111
- # Description:
1112
- # Wait for the browser to get loaded, after the event is being fired.
1113
- #
1114
- def wait
1115
- #ff = FireWatir::Firefox.new
1116
- #ff.wait()
1117
- #puts @container
1118
- @container.wait()
1119
- @@current_level = 0
1120
- end
1121
-
1122
- #
1123
- # Description:
1124
- # Function is used for click events that generates javascript pop up.
1125
- # Doesn't fire the click event immediately instead, it stores the state of the object. User then tells which button
1126
- # is to be clicked in case a javascript pop up comes after clicking the element. Depending upon the button to be clicked
1127
- # the functions 'alert' and 'confirm' are re-defined in JavaScript to return appropriate values either true or false. Then the
1128
- # re-defined functions are send to jssh which then fires the click event of the element using the state
1129
- # stored above. So the click event is fired in the second statement. Therefore, if you are using this function you
1130
- # need to call 'click_js_popup_button()' function in the next statement to actually trigger the click event.
1131
- #
1132
- # Typical Usage:
1133
- # ff.button(:id, "button").click_no_wait()
1134
- # ff.click_js_popup_button("OK")
1135
- #
1136
- #def click_no_wait
1137
- # assert_exists
1138
- # assert_enabled
1139
- #
1140
- # highlight(:set)
1141
- # @@current_js_object = Element.new("#{element_object}", @container)
1142
- #end
1143
-
1144
- #
1145
- # Description:
1146
- # Function to click specified button on the javascript pop up. Currently you can only click
1147
- # either OK or Cancel button.
1148
- # Functions alert and confirm are redefined so that it doesn't causes the JSSH to get blocked. Also this
1149
- # will make Firewatir cross platform.
1150
- #
1151
- # Input:
1152
- # button to be clicked
1153
- #
1154
- #def click_js_popup(button = "OK")
1155
- # jssh_command = "var win = browser.contentWindow;"
1156
- # if(button =~ /ok/i)
1157
- # jssh_command << "var popuptext = '';win.alert = function(param) {popuptext = param; return true; };
1158
- # win.confirm = function(param) {popuptext = param; return true; };"
1159
- # elsif(button =~ /cancel/i)
1160
- # jssh_command << "var popuptext = '';win.alert = function(param) {popuptext = param; return false; };
1161
- # win.confirm = function(param) {popuptext = param; return false; };"
1162
- # end
1163
- # jssh_command.gsub!(/\n/, "")
1164
- # jssh_socket.send("#{jssh_command}\n", 0)
1165
- # read_socket()
1166
- # click_js_popup_creator_button()
1167
- # #jssh_socket.send("popuptext_alert;\n", 0)
1168
- # #read_socket()
1169
- # jssh_socket.send("\n", 0)
1170
- # read_socket()
1171
- #end
1172
-
1173
- #
1174
- # Description:
1175
- # Clicks on button or link or any element that triggers a javascript pop up.
1176
- # Used internally by function click_js_popup.
1177
- #
1178
- #def click_js_popup_creator_button
1179
- # #puts @@current_js_object.element_name
1180
- # jssh_socket.send("#{@@current_js_object.element_name}\n;", 0)
1181
- # temp = read_socket()
1182
- # temp =~ /\[object\s(.*)\]/
1183
- # if $1
1184
- # type = $1
1185
- # else
1186
- # # This is done because in JSSh if you write element name of anchor type
1187
- # # then it displays the link to which it navigates instead of displaying
1188
- # # object type. So above regex match will return nil
1189
- # type = "HTMLAnchorElement"
1190
- # end
1191
- # #puts type
1192
- # case type
1193
- # when "HTMLAnchorElement", "HTMLImageElement"
1194
- # jssh_command = "var event = document.createEvent(\"MouseEvents\");"
1195
- # # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1196
- # jssh_command << "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1197
- # jssh_command << "#{@@current_js_object.element_name}.dispatchEvent(event);\n"
1198
- #
1199
- # jssh_socket.send("#{jssh_command}", 0)
1200
- # read_socket()
1201
- # when "HTMLDivElement", "HTMLSpanElement"
1202
- # jssh_socket.send("typeof(#{element_object}.#{event.downcase});\n", 0)
1203
- # isDefined = read_socket()
1204
- # #puts "is method there : #{isDefined}"
1205
- # if(isDefined != "undefined")
1206
- # if(element_type == "HTMLSelectElement")
1207
- # jssh_command = "var event = document.createEvent(\"HTMLEvents\");
1208
- # event.initEvent(\"click\", true, true);
1209
- # #{element_object}.dispatchEvent(event);"
1210
- # jssh_command.gsub!(/\n/, "")
1211
- # jssh_socket.send("#{jssh_command}\n", 0)
1212
- # read_socket()
1213
- # else
1214
- # jssh_socket.send("#{element_object}.#{event.downcase}();\n", 0)
1215
- # read_socket()
1216
- # end
1217
- # end
1218
- # else
1219
- # jssh_command = "#{@@current_js_object.element_name}.click();\n";
1220
- # jssh_socket.send("#{jssh_command}", 0)
1221
- # read_socket()
1222
- # end
1223
- # @@current_level = 0
1224
- # @@current_js_object = nil
1225
- #end
1226
- #private :click_js_popup_creator_button
1227
-
1228
- #
1229
- # Description:
1230
- # Gets all the cells of the row of a table.
1231
- #
1232
- # Output:
1233
- # Array of table cell elements.
1234
- #
1235
- def get_cells
1236
- assert_exists
1237
- #puts "element name in cells is : #{element_object}"
1238
- if(element_type == "HTMLTableRowElement")
1239
- jssh_socket.send("#{element_object}.cells.length;\n", 0)
1240
- length = read_socket.to_i
1241
- return_array = Array.new(length)
1242
- for i in 0..length - 1 do
1243
- return_array[i] = "#{element_object}.cells[#{i}]"
1244
- end
1245
- return return_array
1246
- else
1247
- puts "The element must be of table row type to execute this function."
1248
- return nil
1249
- end
1250
- end
1251
- private :get_cells
1252
-
1253
- #
1254
- # Description:
1255
- # Traps all the function calls for an element that is not defined and fires them again
1256
- # as it is to the jssh. This can be used in case the element supports properties or methods
1257
- # that are not defined in the corresponding element class or in the base class(Element).
1258
- #
1259
- # Input:
1260
- # methodId - Id of the method that is called.
1261
- # *args - arguments sent to the methods.
1262
- #
1263
- def method_missing(methId, *args)
1264
- methodName = methId.id2name
1265
- #puts "method name is : #{methodName}"
1266
- assert_exists
1267
- #assert_enabled
1268
- methodName = "colSpan" if methodName == "colspan"
1269
- if(methodName =~ /invoke/)
1270
- jssh_command = "#{element_object}."
1271
- for i in args do
1272
- jssh_command << i;
1273
- end
1274
- #puts "#{jssh_command}"
1275
- jssh_socket.send("#{jssh_command};\n", 0)
1276
- return_value = read_socket()
1277
- #puts "return value is : #{return_value}"
1278
- return return_value
1279
- else
1280
- #assert_exists
1281
- #puts "element name is #{element_object}"
1282
-
1283
- # We get method name with trailing '=' when we try to assign a value to a
1284
- # property. So just remove the '=' to get the type
1285
- temp = ""
1286
- assigning_value = false
1287
- if(methodName =~ /(.*)=$/)
1288
- temp = "#{element_object}.#{$1}"
1289
- assigning_value = true
1290
- else
1291
- temp = "#{element_object}.#{methodName}"
1292
- end
1293
- #puts "temp is : #{temp}"
1294
-
1295
- jssh_socket.send("typeof(#{temp});\n", 0)
1296
- method_type = read_socket()
1297
- #puts "method_type is : #{method_type}"
1298
-
1299
- if(assigning_value)
1300
- if(method_type != "boolean" && args[0].class != Fixnum)
1301
- args[0].gsub!("\\", "\\"*4)
1302
- args[0].gsub!("\"", "\\\"")
1303
- args[0].gsub!("\n","\\n")
1304
- jssh_command = "#{element_object}.#{methodName}\"#{args[0]}\""
1305
- else
1306
- jssh_command = "#{element_object}.#{methodName}#{args[0]}"
1307
- end
1308
- #puts "jssh_command is : #{jssh_command}"
1309
- jssh_socket.send("#{jssh_command};\n", 0)
1310
- read_socket()
1311
- return
1312
- end
1313
-
1314
- methodName = "#{element_object}.#{methodName}"
1315
- if(args.length == 0)
1316
- #puts "In if loop #{methodName}"
1317
- if(method_type == "function")
1318
- jssh_command = "#{methodName}();\n"
1319
- else
1320
- jssh_command = "#{methodName};\n"
1321
- end
1322
- else
1323
- #puts "In else loop : #{methodName}"
1324
- jssh_command = "#{methodName}("
1325
-
1326
- count = 0
1327
- if args != nil
1328
- for i in args
1329
- jssh_command << "," if count != 0
1330
- if i.kind_of? Numeric
1331
- jssh_command << i.to_s
1332
- else
1333
- jssh_command << "\"#{i.to_s.gsub(/"/,"\\\"")}\""
1334
- end
1335
- count = count + 1
1336
- end
1337
- end
1338
-
1339
- jssh_command << ");\n"
1340
- end
1341
-
1342
- if(method_type == "boolean")
1343
- jssh_command = jssh_command.gsub("\"false\"", "false")
1344
- jssh_command = jssh_command.gsub("\"true\"", "true")
1345
- end
1346
- #puts "jssh_command is #{jssh_command}"
1347
- jssh_socket.send("#{jssh_command}", 0)
1348
- returnValue = read_socket()
1349
- #puts "return value is : #{returnValue}"
1350
-
1351
- @@current_level = 0
1352
-
1353
- if(method_type == "boolean")
1354
- return false if(returnValue == "false")
1355
- return true if(returnValue == "true")
1356
- elsif(method_type == "number")
1357
- return returnValue.to_i
1358
- else
1359
- return returnValue
1360
- end
1361
- end
1362
- end
1363
-
1364
- end # Element
1
+ module FireWatir
2
+ # Base class for html elements.
3
+ # This is not a class that users would normally access.
4
+ class Element
5
+ include FireWatir::Container
6
+ # Number of spaces that separate the property from the value in the to_s method
7
+ TO_S_SIZE = 14
8
+
9
+ # How to get the nodes using XPath in mozilla.
10
+ ORDERED_NODE_ITERATOR_TYPE = 5
11
+ # To get the number of nodes returned by the xpath expression
12
+ NUMBER_TYPE = 1
13
+ # To get single node value
14
+ FIRST_ORDERED_NODE_TYPE = 9
15
+ # This stores the level to which we have gone finding element inside another element.
16
+ # This is just to make sure that every element has unique name in JSSH.
17
+ @@current_level = 0
18
+ # This stores the name of the element that is about to trigger an Javascript pop up.
19
+ #@@current_js_object = nil
20
+
21
+ attr_accessor :element_name
22
+ #
23
+ # Description:
24
+ # Creates new instance of element. If argument is not nil and is of type string this
25
+ # sets the element_name and element_type property of the object. These properties can
26
+ # be accessed using element_object and element_type methods respectively.
27
+ #
28
+ # Used internally by FireWatir.
29
+ #
30
+ # Input:
31
+ # element - Name of the variable with which the element is referenced in JSSh.
32
+ #
33
+ def initialize(element, container=nil)
34
+ @container = container
35
+ @element_name = element
36
+ @element_type = element_type
37
+ #puts "in initialize "
38
+ #puts caller(0)
39
+ #if(element != nil && element.class == String)
40
+ #@element_name = element
41
+ #elsif(element != nil && element.class == Element)
42
+ # @o = element
43
+ #end
44
+
45
+ #puts "@element_name is #{@element_name}"
46
+ #puts "@element_type is #{@element_type}"
47
+ end
48
+
49
+ private
50
+ def self.def_wrap(ruby_method_name, ole_method_name = nil)
51
+ ole_method_name = ruby_method_name unless ole_method_name
52
+ class_eval "def #{ruby_method_name}
53
+ assert_exists
54
+ # Every element has its name starting from element. If yes then
55
+ # use element_name to send the command to jssh. Else its a number
56
+ # and we are still searching for element, in this case use doc.all
57
+ # array with element_name as index to send command to jssh
58
+ #puts element_object.to_s
59
+ #if(@element_type == 'HTMLDivElement')
60
+ # ole_method_name = 'innerHTML'
61
+ #end
62
+ jssh_socket.send('typeof(' + element_object + '.#{ole_method_name});\n', 0)
63
+ return_type = read_socket()
64
+
65
+ return_value = get_attribute_value(\"#{ole_method_name}\")
66
+
67
+ #if(return_value == '' || return_value == \"null\")
68
+ # return_value = \"\"
69
+ #end
70
+
71
+ if(return_type == \"boolean\")
72
+ return_value = false if return_value == \"false\"
73
+ return_value = true if return_value == \"true\"
74
+ end
75
+ #puts return_value
76
+ @@current_level = 0
77
+ return return_value
78
+ end"
79
+ end
80
+
81
+ def get_attribute_value(attribute_name)
82
+ #if the attribut name is columnLength get number of cells in first row if rows exist.
83
+ case attribute_name
84
+ when "columnLength"
85
+ rowsLength = js_eval_method "columns"
86
+ if (rowsLength != 0 || rowsLength != "")
87
+ return js_eval_method("rows[0].cells.length")
88
+ end
89
+ when "text"
90
+ return text
91
+ when "url", "href", "src", "action", "name"
92
+ return_value = js_eval_method("getAttribute(\"#{attribute_name}\")")
93
+ else
94
+ jssh_command = "var attribute = '';
95
+ if(#{element_object}.#{attribute_name} != undefined)
96
+ attribute = #{element_object}.#{attribute_name};
97
+ else
98
+ attribute = #{element_object}.getAttribute(\"#{attribute_name}\");
99
+ attribute;"
100
+ return_value = js_eval(jssh_command)
101
+ end
102
+ if attribute_name == "value"
103
+ tagName = js_eval_method("tagName").downcase
104
+ type = js_eval_method("type").downcase
105
+
106
+ if tagName == "button" || ["image", "submit", "reset", "button"].include?(type)
107
+ if return_value == "" || return_value == "null"
108
+ return_value = js_eval_method "innerHTML"
109
+ end
110
+ end
111
+ end
112
+
113
+ if return_value == "null" || return_value =~ /\[object\s.*\]/
114
+ return_value = ""
115
+ end
116
+ return return_value
117
+ end
118
+ private :get_attribute_value
119
+
120
+
121
+ #
122
+ # Description:
123
+ # Returns an array of the properties of an element, in a format to be used by the to_s method.
124
+ # additional attributes are returned based on the supplied atributes hash.
125
+ # name, type, id, value and disabled attributes are common to all the elements.
126
+ # This method is used internally by to_s method.
127
+ #
128
+ # Output:
129
+ # Array with values of the following properties:
130
+ # name, type, id, value disabled and the supplied attribues list.
131
+ #
132
+ def string_creator(attributes = nil)
133
+ n = []
134
+ n << "name:".ljust(TO_S_SIZE) + get_attribute_value("name")
135
+ n << "type:".ljust(TO_S_SIZE) + get_attribute_value("type")
136
+ n << "id:".ljust(TO_S_SIZE) + get_attribute_value("id")
137
+ n << "value:".ljust(TO_S_SIZE) + get_attribute_value("value")
138
+ n << "disabled:".ljust(TO_S_SIZE) + get_attribute_value("disabled")
139
+ #n << "style:".ljust(TO_S_SIZE) + get_attribute_value("style")
140
+ #n << "class:".ljust(TO_S_SIZE) + get_attribute_value("className")
141
+
142
+ if(attributes != nil)
143
+ attributes.each do |key,value|
144
+ n << "#{key}:".ljust(TO_S_SIZE) + get_attribute_value(value)
145
+ end
146
+ end
147
+ return n
148
+ end
149
+
150
+ #
151
+ # Description:
152
+ # Sets and clears the colored highlighting on the currently active element.
153
+ #
154
+ # Input:
155
+ # set_or_clear - this can have following two values
156
+ # :set - To set the color of the element.
157
+ # :clear - To clear the color of the element.
158
+ #
159
+ def highlight(set_or_clear)
160
+ if set_or_clear == :set
161
+ #puts "element_name is : #{element_object}"
162
+ jssh_command = " var original_color = #{element_object}.style.background;"
163
+ jssh_command << " #{element_object}.style.background = \"#{DEFAULT_HIGHLIGHT_COLOR}\"; original_color;"
164
+
165
+ # TODO: Need to change this so that it would work if user sets any other color.
166
+ #puts "color is : #{DEFAULT_HIGHLIGHT_COLOR}"
167
+ jssh_socket.send("#{jssh_command}\n", 0)
168
+ @original_color = read_socket()
169
+
170
+ else # BUG: assumes is :clear, but could actually be anything
171
+ begin
172
+ jssh_socket.send("#{element_object}.style.background = \"#{@original_color}\";\n", 0)
173
+ read_socket()
174
+ rescue
175
+ # we could be here for a number of reasons...
176
+ # e.g. page may have reloaded and the reference is no longer valid
177
+ ensure
178
+ @original_color = nil
179
+ end
180
+ end
181
+ end
182
+ protected :highlight
183
+
184
+ #
185
+ # Description:
186
+ # Returns array of rows for a given table. Returns nil if calling element is not of table type.
187
+ #
188
+ # Output:
189
+ # Array of row elements in an table or nil
190
+ #
191
+ def get_rows()
192
+ #puts "#{element_object} and #{element_type}"
193
+ if(element_type == "HTMLTableElement")
194
+ jssh_socket.send("#{element_object}.rows.length;\n", 0)
195
+ length = read_socket().to_i
196
+ #puts "The number of rows in the table are : #{no_of_rows}"
197
+ return_array = Array.new(length)
198
+ for i in 0..length - 1 do
199
+ return_array[i] = "#{element_object}.rows[#{i}]"
200
+ end
201
+ return return_array
202
+ else
203
+ puts "Trying to access rows for Element of type #{element_type}. Element must be of table type to execute this function."
204
+ return nil
205
+ end
206
+ end
207
+ private :get_rows
208
+
209
+ def set_specifier(how, what)
210
+ if how.class == Hash and what.nil?
211
+ specifiers = how
212
+ else
213
+ specifiers = {how => what}
214
+ end
215
+
216
+ @specifiers = {:index => 1} # default if not specified
217
+
218
+ specifiers.each do |how, what|
219
+ what = what.to_i if how == :index
220
+ how = :href if how == :url
221
+ how = :value if how == :caption
222
+ how = :class if how == :class_name
223
+
224
+ @specifiers[how] = what
225
+ end
226
+ end
227
+
228
+ #
229
+ # Description:
230
+ # Locates the element on the page depending upon the parameters passed. Logic for locating the element is written
231
+ # in JavaScript and then send to JSSh; so that we don't make small round-trips via socket to JSSh. This is done to
232
+ # improve the performance for locating the element.
233
+ #
234
+ # Input:
235
+ # tag - Tag name of the element to be located like "input", "a" etc. This is case insensitive.
236
+ # how - The attribute by which you want to locate the element like id, name etc. You can use any attribute-value pair
237
+ # that uniquely identifies that element on the page. If there are more that one element that have identical
238
+ # attribute-value pair then first element that is found while traversing the DOM will be returned.
239
+ # what - The value of the attribute specified by how.
240
+ # types - Used if that HTML element to be located has different type like input can be of type image, button etc.
241
+ # Default value is nil
242
+ # value - This is used only in case of radio buttons where they have same name but different value.
243
+ #
244
+ # Output:
245
+ # Returns nil if unable to locate the element, else return the element.
246
+ #
247
+ def locate_tagged_element(tag, how, what, types = nil, value = nil)
248
+ #puts caller(0)
249
+ # how = :value if how == :caption
250
+ # how = :href if how == :url
251
+ set_specifier(how, what)
252
+ #puts "(locate_tagged_element)current element is : #{@container.class} and tag is #{tag}"
253
+ # If there is no current element i.e. element in current context we are searching the whole DOM tree.
254
+ # So get all the elements.
255
+
256
+ if(types != nil and types.include?("button"))
257
+ jssh_command = "var isButtonElement = true;"
258
+ else
259
+ jssh_command = "var isButtonElement = false;"
260
+ end
261
+
262
+ # Because in both the below cases we need to get element with respect to document.
263
+ # when we locate a frame document is automatically adjusted to point to HTML inside the frame
264
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
265
+ #end
266
+ #if(@@current_element_object == "")
267
+ jssh_command << "var elements_#{tag} = null; elements_#{tag} = #{@container.document_var}.getElementsByTagName(\"#{tag}\");"
268
+ if(types != nil and (types.include?("textarea") or types.include?("button")) )
269
+ jssh_command << "elements_#{tag} = #{@container.document_var}.body.getElementsByTagName(\"*\");"
270
+ end
271
+ # @@has_changed = true
272
+ else
273
+ #puts "container name is: " + @container.element_name
274
+ #locate if defined? locate
275
+ #@container.locate
276
+ jssh_command << "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
277
+ if(types != nil and (types.include?("textarea") or types.include?("button") ) )
278
+ jssh_command << "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
279
+ end
280
+ # @@has_changed = false
281
+ end
282
+
283
+
284
+ if(types != nil)
285
+ jssh_command << "var types = new Array("
286
+ count = 0
287
+ types.each do |type|
288
+ if count == 0
289
+ jssh_command << "\"#{type}\""
290
+ count += 1
291
+ else
292
+ jssh_command << ",\"#{type}\""
293
+ end
294
+ end
295
+ jssh_command << ");"
296
+ else
297
+ jssh_command << "var types = null;"
298
+ end
299
+ #jssh_command << "var elements = #{element_object}.getElementsByTagName('*');"
300
+ jssh_command << "var object_index = 1; var o = null; var element_name = \"\";"
301
+
302
+ case value
303
+ when Regexp
304
+ jssh_command << "var value = #{ rb_regexp_to_js(value) };"
305
+ when nil
306
+ jssh_command << "var value = null;"
307
+ else
308
+ jssh_command << "var value = \"#{value}\";"
309
+ end
310
+
311
+ #add hash arrays
312
+ sKey = "var hashKeys = new Array("
313
+ sVal = "var hashValues = new Array("
314
+ @specifiers.each do |k,v|
315
+ sKey += "\"#{k}\","
316
+ if v.is_a?(Regexp)
317
+ sVal += "#{rb_regexp_to_js(v)},"
318
+ else
319
+ sVal += "\"#{v}\","
320
+ end
321
+ end
322
+ sKey = sKey[0..sKey.length-2]
323
+ sVal = sVal[0..sVal.length-2]
324
+ jssh_command << sKey + ");"
325
+ jssh_command << sVal + ");"
326
+
327
+ #index
328
+ jssh_command << "var target_index = 1;
329
+ for(var k=0; k<hashKeys.length; k++)
330
+ {
331
+ if(hashKeys[k] == \"index\")
332
+ {
333
+ target_index = parseInt(hashValues[k]);
334
+ break;
335
+ }
336
+ }"
337
+
338
+ #jssh_command << "elements.length;"
339
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
340
+
341
+ jssh_command << "for(var i=0; i<elements_#{tag}.length; i++)
342
+ {
343
+ if(element_name != \"\") break;
344
+ var element = elements_#{tag}[i];"
345
+ else
346
+ jssh_command << "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
347
+ {
348
+ if(element_name != \"\") break;
349
+ var element = elements_#{@@current_level}_#{tag}[i];"
350
+ end
351
+
352
+ # Because in IE for button the value of "value" attribute also corresponds to the innerHTML if value attribute
353
+ # is not supplied. For e.g.: <button>Sign In</button>, in this case value of "value" attribute is "Sign In"
354
+ # though value attribute is not supplied. But for Firefox value of "value" attribute is null. So to make sure
355
+ # script runs on both IE and Watir we are also considering innerHTML if element is of button type.
356
+ jssh_command << " var attribute = \"\";
357
+ var same_type = false;
358
+ if(types)
359
+ {
360
+ for(var j=0; j<types.length; j++)
361
+ {
362
+ if(types[j] == element.type || types[j] == element.tagName)
363
+ {
364
+ same_type = true;
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ else
370
+ {
371
+ same_type = true;
372
+ }
373
+ if(same_type == true)
374
+ {
375
+ var how = \"\";
376
+ var what = null;
377
+ attribute = \"\";
378
+ for(var k=0; k<hashKeys.length; k++)
379
+ {
380
+ how = hashKeys[k];
381
+ what = hashValues[k];
382
+
383
+ if(how == \"index\")
384
+ {
385
+ attribute = parseInt(what);
386
+ what = parseInt(what);
387
+ }
388
+ else
389
+ {
390
+ if(how == \"text\")
391
+ {
392
+ attribute = element.textContent.replace(/\\xA0/g,' ').replace(/^\\s+|\\s+$/g, '').replace(/\\s+/g, ' ')
393
+ }
394
+ else
395
+ {
396
+ if(how == \"href\" || how == \"src\" || how == \"action\" || how == \"name\")
397
+ {
398
+ attribute = element.getAttribute(how);
399
+ }
400
+ else
401
+ {
402
+ if(eval(\"element.\"+how) != undefined)
403
+ attribute = eval(\"element.\"+how);
404
+ else
405
+ attribute = element.getAttribute(how);
406
+ }
407
+ }
408
+ if(\"value\" == how && isButtonElement && (attribute == null || attribute == \"\"))
409
+ {
410
+ attribute = element.innerHTML;
411
+ }
412
+ }
413
+ if(attribute == \"\") o = 'NoMethodError';
414
+ var found = false;
415
+ if (typeof what == \"object\" || typeof what == \"function\")
416
+ {
417
+ var regExp = new RegExp(what);
418
+ found = regExp.test(attribute);
419
+ }
420
+ else
421
+ {
422
+ found = (attribute == what);
423
+ }"
424
+
425
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
426
+ jssh_command << " if(found)
427
+ {
428
+ if(value)
429
+ {
430
+ if(element.value == value || (value.test && value.test(element.value)))
431
+ {
432
+ o = element;
433
+ element_name = \"elements_#{tag}[\" + i + \"]\";
434
+ }
435
+ else
436
+ break;
437
+ }
438
+ else
439
+ {
440
+ o = element;
441
+ element_name = \"elements_#{tag}[\" + i + \"]\";
442
+ }
443
+ }"
444
+ else
445
+ jssh_command << " if(found)
446
+ {
447
+ if(value)
448
+ {
449
+ if(element.value == value || (value.test && value.test(element.value)))
450
+ {
451
+ o = element;
452
+ element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
453
+ }
454
+ else
455
+ break;
456
+ }
457
+ else
458
+ {
459
+ o = element;
460
+ element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
461
+ }
462
+ }"
463
+ end
464
+
465
+ jssh_command << "
466
+ else {
467
+ o = null;
468
+ element_name = \"\";
469
+ break;
470
+ }
471
+ }
472
+ if(element_name != \"\")
473
+ {
474
+ if(target_index == object_index)
475
+ {
476
+ break;
477
+ }
478
+ else if(target_index < object_index)
479
+ {
480
+ element_name = \"\";
481
+ o = null;
482
+ break;
483
+ }
484
+ else
485
+ {
486
+ object_index += 1;
487
+ element_name = \"\";
488
+ o = null;
489
+ }
490
+ }
491
+ }
492
+ }
493
+ element_name;"
494
+
495
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
496
+ jssh_command.gsub!(/\n/, "")
497
+ #puts jssh_command
498
+ #out = File.new("c:\\result.log", "w")
499
+ #out << jssh_command
500
+ #out.close
501
+ jssh_socket.send("#{jssh_command};\n", 0)
502
+ element_name = read_socket();
503
+ #puts "element name in find control is : #{element_name}"
504
+ @@current_level = @@current_level + 1
505
+ #puts @container
506
+ #puts element_name
507
+ if(element_name != "")
508
+ return element_name #Element.new(element_name, @container)
509
+ else
510
+ return nil
511
+ end
512
+ end
513
+
514
+ def rb_regexp_to_js(regexp)
515
+ old_exp = regexp.to_s
516
+ new_exp = regexp.inspect.sub(/\w*$/, '')
517
+ flags = old_exp.slice(2, old_exp.index(':') - 2)
518
+
519
+ for i in 0..flags.length do
520
+ flag = flags[i, 1]
521
+ if(flag == '-')
522
+ break;
523
+ else
524
+ new_exp << flag
525
+ end
526
+ end
527
+
528
+ new_exp
529
+ end
530
+
531
+ #
532
+ # Description:
533
+ # Locates frame element. Logic for locating the frame is written in JavaScript so that we don't make small
534
+ # round trips to JSSh using socket. This is done to improve the performance for locating the element.
535
+ #
536
+ # Input:
537
+ # how - The attribute for locating the frame. You can use any attribute-value pair that uniquely identifies
538
+ # the frame on the page. If there are more than one frames that have identical attribute-value pair
539
+ # then first frame that is found while traversing the DOM will be returned.
540
+ # what - Value of the attribute specified by how
541
+ #
542
+ # Output:
543
+ # Nil if unable to locate frame, else return the Frame element.
544
+ #
545
+ # TODO/FIX: If multiple tabs are open on the current window, will count frames from every tab, not just the current tab.
546
+ #
547
+ def locate_frame(how, what)
548
+ # Get all the frames the are there on the page.
549
+ #puts "how is #{how} and what is #{what}"
550
+ jssh_command = ""
551
+ if(@container.class == FireWatir::Firefox)
552
+ # In firefox 3 if you write Frame Name then it will not show anything. So we add .toString function to every element.
553
+ jssh_command = "var frameset = #{@container.window_var}.frames;
554
+ var elements_frames = new Array();
555
+ for(var i = 0; i < frameset.length; i++)
556
+ {
557
+ var frames = frameset[i].frames;
558
+ for(var j = 0; j < frames.length; j++)
559
+ {
560
+ frames[j].frameElement.toString = function() { return '[object HTMLFrameElement]'; };
561
+ elements_frames.push(frames[j].frameElement);
562
+
563
+ }
564
+ }"
565
+ else
566
+ jssh_command = "var frames = #{@container.element_name}.contentWindow.frames;
567
+ var elements_frames_#{@@current_level} = new Array();
568
+ for(var i = 0; i < frames.length; i++)
569
+ {
570
+ elements_frames_#{@@current_level}.push(frames[i].frameElement);
571
+ }"
572
+ end
573
+
574
+ jssh_command << " var element_name = ''; var object_index = 1;var attribute = '';
575
+ var element = '';"
576
+ if(@container.class == FireWatir::Firefox)
577
+ jssh_command << "for(var i = 0; i < elements_frames.length; i++)
578
+ {
579
+ element = elements_frames[i];"
580
+ else
581
+ jssh_command << "for(var i = 0; i < elements_frames_#{@@current_level}.length; i++)
582
+ {
583
+ element = elements_frames_#{@@current_level}[i];"
584
+ end
585
+ jssh_command << " if(\"index\" == \"#{how}\")
586
+ {
587
+ attribute = object_index; object_index += 1;
588
+ }
589
+ else
590
+ {
591
+ attribute = element.getAttribute(\"#{how}\");
592
+ if(attribute == \"\" || attribute == null)
593
+ {
594
+ attribute = element.#{how};
595
+ }
596
+ }
597
+ var found = false;"
598
+ if(what.class == Regexp)
599
+ oldRegExp = what.to_s
600
+ newRegExp = "/" + what.source + "/"
601
+ flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
602
+
603
+ for i in 0..flags.length do
604
+ flag = flags[i, 1]
605
+ if(flag == '-')
606
+ break;
607
+ else
608
+ newRegExp << flag
609
+ end
610
+ end
611
+ #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
612
+ jssh_command << " var regExp = new RegExp(#{newRegExp});
613
+ found = regExp.test(attribute);"
614
+ elsif(how == :index)
615
+ jssh_command << " found = (attribute == #{what});"
616
+ else
617
+ jssh_command << " found = (attribute == \"#{what}\");"
618
+ end
619
+
620
+ jssh_command << " if(found)
621
+ {"
622
+ if(@container.class == FireWatir::Firefox)
623
+ jssh_command << " element_name = \"elements_frames[\" + i + \"]\";
624
+ #{@container.document_var} = elements_frames[i].contentDocument;
625
+ #{@container.body_var} = #{@container.document_var}.body;"
626
+ else
627
+ jssh_command << " element_name = \"elements_frames_#{@@current_level}[\" + i + \"]\";
628
+ #{@container.document_var} = elements_frames_#{@@current_level}[i].contentDocument;
629
+ #{@container.body_var} = #{@container.document_var}.body;"
630
+ end
631
+ jssh_command << " break;
632
+ }
633
+ }
634
+ element_name;"
635
+
636
+ jssh_command.gsub!("\n", "")
637
+ #puts "jssh_command for finding frame is : #{jssh_command}"
638
+
639
+ jssh_socket.send("#{jssh_command};\n", 0)
640
+ element_name = read_socket()
641
+ @@current_level = @@current_level + 1
642
+ #puts "element_name for frame is : #{element_name}"
643
+
644
+ if(element_name != "")
645
+ return element_name
646
+ else
647
+ return nil
648
+ end
649
+ end
650
+
651
+ def get_frame_html
652
+ jssh_socket.send("var htmlelem = #{@container.document_var}.getElementsByTagName('html')[0]; htmlelem.innerHTML;\n", 0)
653
+ #jssh_socket.send("body.innerHTML;\n", 0)
654
+ result = read_socket()
655
+ return "<html>" + result + "</html>"
656
+ end
657
+
658
+ def submit_form
659
+ #puts "form name is : #{element_object}"
660
+ jssh_socket.send("#{element_object}.submit();\n" , 0)
661
+ read_socket()
662
+ end
663
+
664
+ public
665
+
666
+ #
667
+ #
668
+ # Description:
669
+ # Matches the given text with the current text shown in the browser for that particular element.
670
+ #
671
+ # Input:
672
+ # target - Text to match. Can be a string or regex
673
+ #
674
+ # Output:
675
+ # Returns the index if the specified text was found.
676
+ # Returns matchdata object if the specified regexp was found.
677
+ #
678
+ def contains_text(target)
679
+ #puts "Text to match is : #{match_text}"
680
+ #puts "Html is : #{self.text}"
681
+ if target.kind_of? Regexp
682
+ self.text.match(target)
683
+ elsif target.kind_of? String
684
+ self.text.index(target)
685
+ else
686
+ raise TypeError, "Argument #{target} should be a string or regexp."
687
+ end
688
+ end
689
+
690
+
691
+ def inspect
692
+ '#<%s:0x%x located=%s how=%s what=%s>' % [self.class, hash*2, !!@o, @how.inspect, @what.inspect]
693
+ end
694
+
695
+ #
696
+ # Description:
697
+ # Returns array of elements that matches a given XPath query.
698
+ # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
699
+ # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
700
+ # Used internally by Firewatir use ff.elements_by_xpath instead.
701
+ #
702
+ # Input:
703
+ # xpath - The xpath expression or query.
704
+ #
705
+ # Output:
706
+ # Array of elements that matched the xpath expression provided as parameter.
707
+ #
708
+ def elements_by_xpath(container, xpath)
709
+ rand_no = rand(1000)
710
+ #jssh_command = "var xpathResult = document.evaluate(\"count(#{xpath})\", document, null, #{NUMBER_TYPE}, null); xpathResult.numberValue;"
711
+ #jssh_socket.send("#{jssh_command}\n", 0);
712
+ #node_count = read_socket()
713
+ xpath.gsub!("\"", "\\\"")
714
+ jssh_command = "var element_xpath_#{rand_no} = new Array();"
715
+
716
+ jssh_command << "var result = #{@container.document_var}.evaluate(\"#{xpath}\", #{@container.document_var}, null, #{ORDERED_NODE_ITERATOR_TYPE}, null);
717
+ var iterate = result.iterateNext();
718
+ while(iterate)
719
+ {
720
+ element_xpath_#{rand_no}.push(iterate);
721
+ iterate = result.iterateNext();
722
+ }
723
+ element_xpath_#{rand_no}.length;
724
+ "
725
+
726
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
727
+ jssh_command.gsub!(/\n/, "")
728
+ #puts jssh_command
729
+ jssh_socket.send("#{jssh_command};\n", 0)
730
+ node_count = read_socket()
731
+ #puts "value of count is : #{node_count}"
732
+
733
+ elements = Array.new(node_count.to_i)
734
+
735
+ for i in 0..elements.length - 1 do
736
+ elements[i] = "element_xpath_#{rand_no}[#{i}]"
737
+ end
738
+
739
+ return elements;
740
+ end
741
+
742
+ #
743
+ # Description:
744
+ # Returns first element found while traversing the DOM; that matches an given XPath query.
745
+ # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
746
+ # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
747
+ # Used internally by Firewatir use ff.element_by_xpath instead.
748
+ #
749
+ # Input:
750
+ # xpath - The xpath expression or query.
751
+ #
752
+ # Output:
753
+ # First element in DOM that matched the XPath expression or query.
754
+ #
755
+ def element_by_xpath(container, xpath)
756
+ #puts "here locating element by xpath"
757
+ rand_no = rand(1000)
758
+ xpath.gsub!("\"", "\\\"")
759
+ jssh_command = "var element_xpath_#{rand_no} = null; element_xpath_#{rand_no} = #{@container.document_var}.evaluate(\"#{xpath}\", #{container.document_var}, null, #{FIRST_ORDERED_NODE_TYPE}, null).singleNodeValue; element_xpath_#{rand_no};"
760
+
761
+ jssh_socket.send("#{jssh_command}\n", 0)
762
+ result = read_socket()
763
+ #puts "command send to jssh is : #{jssh_command}"
764
+ #puts "result is : #{result}"
765
+ if(result == "null" || result == "" || result.include?("exception"))
766
+ @@current_level = 0
767
+ return nil
768
+ else
769
+ @@current_level += 1
770
+ return "element_xpath_#{rand_no}"
771
+ end
772
+ end
773
+
774
+ #
775
+ # Description:
776
+ # Returns the name of the element with which we can access it in JSSh.
777
+ # Used internally by Firewatir to execute methods, set properties or return property value for the element.
778
+ #
779
+ # Output:
780
+ # Name of the variable with which element is referenced in JSSh
781
+ #
782
+ def element_object
783
+ #puts caller.join("\n")
784
+ #puts "In element_object element name is : #{@element_name}"
785
+ #puts "in element_object : #{@container.class}"
786
+ #if(@container.class == FireWatir::Firefox)
787
+ return @element_name #if @element_name != nil
788
+ #else
789
+ # return @container.element_name
790
+ #end
791
+ #return @o.element_name if @o != nil
792
+ end
793
+ private :element_object
794
+
795
+ #
796
+ # Description:
797
+ # Returns the type of element. For e.g.: HTMLAnchorElement. used internally by Firewatir
798
+ #
799
+ # Output:
800
+ # Type of the element.
801
+ #
802
+ def element_type
803
+ #puts "in element_type object is : #{element_object}"
804
+ # Get the type of the element.
805
+ jssh_socket.send("#{element_object};\n", 0)
806
+ temp = read_socket()
807
+
808
+ #puts "#{element_object} and type is #{temp}"
809
+ temp =~ /\[object\s(.*)\]/
810
+ if $1
811
+ return $1
812
+ else
813
+ # This is done because in JSSh if you write element name of anchor type
814
+ # then it displays the link to which it navigates instead of displaying
815
+ # object type. So above regex match will return nil
816
+ return "HTMLAnchorElement"
817
+ end
818
+ end
819
+ #private :element_type
820
+
821
+ #
822
+ # Description:
823
+ # Fires the provided event for an element and by default waits for the action to get completed.
824
+ #
825
+ # Input:
826
+ # event - Event to be fired like "onclick", "onchange" etc.
827
+ # wait - Whether to wait for the action to get completed or not. By default its true.
828
+ #
829
+ # TODO: Provide ability to specify event parameters like keycode for key events, and click screen
830
+ # coordinates for mouse events.
831
+ def fire_event(event, wait = true)
832
+ assert_exists()
833
+ event = event.to_s # in case event was given as a symbol
834
+
835
+ event = event.downcase
836
+
837
+ event =~ /on(.*)/i
838
+ event = $1 if $1
839
+
840
+ # check if we've got an old-school on-event
841
+ #jssh_socket.send("typeof(#{element_object}.#{event});\n", 0)
842
+ #is_defined = read_socket()
843
+
844
+ # info about event types harvested from:
845
+ # http://www.howtocreate.co.uk/tutorials/javascript/domevents
846
+ case event
847
+ when 'abort', 'blur', 'change', 'error', 'focus', 'load', 'reset', 'resize',
848
+ 'scroll', 'select', 'submit', 'unload'
849
+ dom_event_type = 'HTMLEvents'
850
+ dom_event_init = "initEvent(\"#{event}\", true, true)"
851
+ when 'keydown', 'keypress', 'keyup'
852
+ dom_event_type = 'KeyEvents'
853
+ # Firefox has a proprietary initializer for keydown/keypress/keyup.
854
+ # Args are as follows:
855
+ # 'type', bubbles, cancelable, windowObject, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
856
+ dom_event_init = "initKeyEvent(\"#{event}\", true, true, #{@container.window_var}, false, false, false, false, 0, 0)"
857
+ when 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover',
858
+ 'mouseup'
859
+ dom_event_type = 'MouseEvents'
860
+ # Args are as follows:
861
+ # 'type', bubbles, cancelable, windowObject, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget
862
+ dom_event_init = "initMouseEvent(\"#{event}\", true, true, #{@container.window_var}, 1, 0, 0, 0, 0, false, false, false, false, 0, null)"
863
+ else
864
+ dom_event_type = 'HTMLEvents'
865
+ dom_event_init = "initEvents(\"#{event}\", true, true)"
866
+ end
867
+
868
+ if(element_type == "HTMLSelectElement")
869
+ dom_event_type = 'HTMLEvents'
870
+ dom_event_init = "initEvent(\"#{event}\", true, true)"
871
+ end
872
+
873
+
874
+ jssh_command = "var event = #{@container.document_var}.createEvent(\"#{dom_event_type}\"); "
875
+ jssh_command << "event.#{dom_event_init}; "
876
+ jssh_command << "#{element_object}.dispatchEvent(event);"
877
+
878
+ #puts "JSSH COMMAND:\n#{jssh_command}\n"
879
+
880
+ jssh_socket.send("#{jssh_command}\n", 0)
881
+ read_socket() if wait
882
+ wait() if wait
883
+
884
+ @@current_level = 0
885
+ end
886
+ alias fireEvent fire_event
887
+
888
+ #
889
+ # Description:
890
+ # Returns the value of the specified attribute of an element.
891
+ #
892
+ def attribute_value(attribute_name)
893
+ #puts attribute_name
894
+ assert_exists()
895
+ return_value = get_attribute_value(attribute_name)
896
+ @@current_level = 0
897
+ return return_value
898
+ end
899
+
900
+ #
901
+ # Description:
902
+ # Checks if element exists or not. Raises UnknownObjectException if element doesn't exists.
903
+ #
904
+ def assert_exists
905
+ unless exists?
906
+ raise UnknownObjectException.new(
907
+ Watir::Exception.message_for_unable_to_locate(@how, @what))
908
+ end
909
+ end
910
+
911
+ #
912
+ # Description:
913
+ # Checks if element is enabled or not. Raises ObjectDisabledException if object is disabled and
914
+ # you are trying to use the object.
915
+ #
916
+ def assert_enabled
917
+ unless enabled?
918
+ raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
919
+ end
920
+ end
921
+
922
+ #
923
+ # Description:
924
+ # First checks if element exists or not. Then checks if element is enabled or not.
925
+ #
926
+ # Output:
927
+ # Returns true if element exists and is enabled, else returns false.
928
+ #
929
+ def enabled?
930
+ assert_exists
931
+ value = js_eval_method "disabled"
932
+ @@current_level = 0
933
+ return true if(value == "false")
934
+ return false if(value == "true")
935
+ return value
936
+ end
937
+
938
+ #
939
+ # Description:
940
+ # Checks element for display: none or visibility: hidden, these are
941
+ # the most common methods to hide an html element
942
+
943
+ def visible?
944
+ assert_exists
945
+ val = js_eval "var val = 'true'; var str = ''; var obj = #{element_object}; while (obj != null) { try { str = #{@container.document_var}.defaultView.getComputedStyle(obj,null).visibility; if (str=='hidden') { val = 'false'; break; } str = #{@container.document_var}.defaultView.getComputedStyle(obj,null).display; if (str=='none') { val = 'false'; break; } } catch(err) {} obj = obj.parentNode; } val;"
946
+ return (val == 'false')? false: true
947
+ end
948
+
949
+
950
+ #
951
+ # Description:
952
+ # Checks if element exists or not. If element is not located yet then first locates the element.
953
+ #
954
+ # Output:
955
+ # True if element exists, false otherwise.
956
+ #
957
+ def exists?
958
+ # puts "element is : #{element_object}"
959
+ # puts caller(0)
960
+ # If elements array has changed locate the element again. So that the element name points to correct element.
961
+ if(element_object == nil || element_object == "")
962
+ @@current_level = 0
963
+ #puts "locating element"
964
+ locate if respond_to?(:locate)
965
+ if(@element_name == nil || @element_name == "")
966
+ return false
967
+ else
968
+ #puts caller(0)
969
+ #puts "element name is : #{@element_name}"
970
+ return true
971
+ end
972
+ else
973
+ #puts "not locating the element again"
974
+ return true
975
+ end
976
+ #@@current_level = 0
977
+ #if(element_object == nil || element_object == "")
978
+ # return false
979
+ #else
980
+ # return true
981
+ #end
982
+ rescue UnknownFrameException
983
+ false
984
+ end
985
+ alias exist? exists?
986
+
987
+ #
988
+ # Description:
989
+ # Returns the text of the element.
990
+ #
991
+ # Output:
992
+ # Text of the element.
993
+ #
994
+ def text()
995
+ assert_exists
996
+ element = (element_type == "HTMLFrameElement") ? "body" : element_object
997
+ return_value = js_eval("#{element}.textContent.replace(/\\xA0/g, ' ').replace(/\\s+/g, ' ')").strip
998
+ @@current_level = 0
999
+ return return_value
1000
+ end
1001
+ alias innerText text
1002
+
1003
+ # Returns the name of the element (as defined in html)
1004
+ def_wrap :name
1005
+ # Returns the id of the element
1006
+ def_wrap :id
1007
+ # Returns whether the element is disabled
1008
+ def disabled
1009
+ ! enabled?
1010
+ end
1011
+ alias disabled? disabled
1012
+ # Returns the state of the element
1013
+ def_wrap :checked
1014
+ # Returns the value of the element
1015
+ def_wrap :value
1016
+ # Returns the title of the element
1017
+ def_wrap :title
1018
+ # Returns the value of 'alt' attribute in case of Image element.
1019
+ def_wrap :alt
1020
+ # Returns the value of 'href' attribute in case of Anchor element.
1021
+ def_wrap :src
1022
+ # Returns the type of the element. Use in case of Input element only.
1023
+ def_wrap :type
1024
+ # Returns the url the Anchor element points to.
1025
+ def_wrap :href
1026
+ # Return the ID of the control that this label is associated with
1027
+ def_wrap :for, :htmlFor
1028
+ # Returns the class name of the element
1029
+ def_wrap :class_name, :className
1030
+ # Return the html of the object
1031
+ def_wrap :html, :innerHTML
1032
+ # Return the action of form
1033
+ def_wrap :action
1034
+
1035
+ #
1036
+ # Description:
1037
+ # Display basic details about the object. Sample output for a button is shown.
1038
+ # Raises UnknownObjectException if the object is not found.
1039
+ # name b4
1040
+ # type button
1041
+ # id b5
1042
+ # value Disabled Button
1043
+ # disabled true
1044
+ #
1045
+ # Output:
1046
+ # Array with value of properties shown above.
1047
+ #
1048
+ def to_s(attributes=nil)
1049
+ #puts "here in to_s"
1050
+ #puts caller(0)
1051
+ assert_exists
1052
+ if(element_type == "HTMLTableCellElement")
1053
+ return text()
1054
+ else
1055
+ result = string_creator(attributes).join("\n")
1056
+ @@current_level = 0
1057
+ return result
1058
+ end
1059
+ end
1060
+
1061
+ #
1062
+ # Description:
1063
+ # Function to fire click event on elements.
1064
+ #
1065
+ def click
1066
+ assert_exists
1067
+ assert_enabled
1068
+
1069
+ highlight(:set)
1070
+ #puts "#{element_object} and #{element_type}"
1071
+ case element_type
1072
+
1073
+ when "HTMLAnchorElement", "HTMLImageElement"
1074
+ # Special check for link or anchor tag. Because click() doesn't work on links.
1075
+ # More info: http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-48250443
1076
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=148585
1077
+
1078
+ jssh_command = "var event = #{@container.document_var}.createEvent(\"MouseEvents\");"
1079
+
1080
+ # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1081
+ jssh_command << "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1082
+ jssh_command << "#{element_object}.dispatchEvent(event);\n"
1083
+
1084
+ #puts "jssh_command is: #{jssh_command}"
1085
+ jssh_socket.send("#{jssh_command}", 0)
1086
+ read_socket()
1087
+ else
1088
+ jssh_socket.send("typeof(#{element_object}.click);\n", 0)
1089
+ isDefined = read_socket()
1090
+ if(isDefined == "undefined")
1091
+ fire_event("onclick")
1092
+ else
1093
+ jssh_socket.send("#{element_object}.click();\n" , 0)
1094
+ read_socket()
1095
+ end
1096
+ end
1097
+ highlight(:clear)
1098
+ # Wait for firefox to reload.
1099
+ wait()
1100
+ end
1101
+
1102
+ #
1103
+ # Description:
1104
+ # Document var. Unfinished.
1105
+ #
1106
+ def document_var
1107
+ "document"
1108
+ end
1109
+
1110
+ #
1111
+ # Description:
1112
+ # Wait for the browser to get loaded, after the event is being fired.
1113
+ #
1114
+ def wait
1115
+ #ff = FireWatir::Firefox.new
1116
+ #ff.wait()
1117
+ #puts @container
1118
+ @container.wait()
1119
+ @@current_level = 0
1120
+ end
1121
+
1122
+ #
1123
+ # Description:
1124
+ # Function is used for click events that generates javascript pop up.
1125
+ # Doesn't fire the click event immediately instead, it stores the state of the object. User then tells which button
1126
+ # is to be clicked in case a javascript pop up comes after clicking the element. Depending upon the button to be clicked
1127
+ # the functions 'alert' and 'confirm' are re-defined in JavaScript to return appropriate values either true or false. Then the
1128
+ # re-defined functions are send to jssh which then fires the click event of the element using the state
1129
+ # stored above. So the click event is fired in the second statement. Therefore, if you are using this function you
1130
+ # need to call 'click_js_popup_button()' function in the next statement to actually trigger the click event.
1131
+ #
1132
+ # Typical Usage:
1133
+ # ff.button(:id, "button").click_no_wait()
1134
+ # ff.click_js_popup_button("OK")
1135
+ #
1136
+ #def click_no_wait
1137
+ # assert_exists
1138
+ # assert_enabled
1139
+ #
1140
+ # highlight(:set)
1141
+ # @@current_js_object = Element.new("#{element_object}", @container)
1142
+ #end
1143
+
1144
+ #
1145
+ # Description:
1146
+ # Function to click specified button on the javascript pop up. Currently you can only click
1147
+ # either OK or Cancel button.
1148
+ # Functions alert and confirm are redefined so that it doesn't causes the JSSH to get blocked. Also this
1149
+ # will make Firewatir cross platform.
1150
+ #
1151
+ # Input:
1152
+ # button to be clicked
1153
+ #
1154
+ #def click_js_popup(button = "OK")
1155
+ # jssh_command = "var win = browser.contentWindow;"
1156
+ # if(button =~ /ok/i)
1157
+ # jssh_command << "var popuptext = '';win.alert = function(param) {popuptext = param; return true; };
1158
+ # win.confirm = function(param) {popuptext = param; return true; };"
1159
+ # elsif(button =~ /cancel/i)
1160
+ # jssh_command << "var popuptext = '';win.alert = function(param) {popuptext = param; return false; };
1161
+ # win.confirm = function(param) {popuptext = param; return false; };"
1162
+ # end
1163
+ # jssh_command.gsub!(/\n/, "")
1164
+ # jssh_socket.send("#{jssh_command}\n", 0)
1165
+ # read_socket()
1166
+ # click_js_popup_creator_button()
1167
+ # #jssh_socket.send("popuptext_alert;\n", 0)
1168
+ # #read_socket()
1169
+ # jssh_socket.send("\n", 0)
1170
+ # read_socket()
1171
+ #end
1172
+
1173
+ #
1174
+ # Description:
1175
+ # Clicks on button or link or any element that triggers a javascript pop up.
1176
+ # Used internally by function click_js_popup.
1177
+ #
1178
+ #def click_js_popup_creator_button
1179
+ # #puts @@current_js_object.element_name
1180
+ # jssh_socket.send("#{@@current_js_object.element_name}\n;", 0)
1181
+ # temp = read_socket()
1182
+ # temp =~ /\[object\s(.*)\]/
1183
+ # if $1
1184
+ # type = $1
1185
+ # else
1186
+ # # This is done because in JSSh if you write element name of anchor type
1187
+ # # then it displays the link to which it navigates instead of displaying
1188
+ # # object type. So above regex match will return nil
1189
+ # type = "HTMLAnchorElement"
1190
+ # end
1191
+ # #puts type
1192
+ # case type
1193
+ # when "HTMLAnchorElement", "HTMLImageElement"
1194
+ # jssh_command = "var event = document.createEvent(\"MouseEvents\");"
1195
+ # # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1196
+ # jssh_command << "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1197
+ # jssh_command << "#{@@current_js_object.element_name}.dispatchEvent(event);\n"
1198
+ #
1199
+ # jssh_socket.send("#{jssh_command}", 0)
1200
+ # read_socket()
1201
+ # when "HTMLDivElement", "HTMLSpanElement"
1202
+ # jssh_socket.send("typeof(#{element_object}.#{event.downcase});\n", 0)
1203
+ # isDefined = read_socket()
1204
+ # #puts "is method there : #{isDefined}"
1205
+ # if(isDefined != "undefined")
1206
+ # if(element_type == "HTMLSelectElement")
1207
+ # jssh_command = "var event = document.createEvent(\"HTMLEvents\");
1208
+ # event.initEvent(\"click\", true, true);
1209
+ # #{element_object}.dispatchEvent(event);"
1210
+ # jssh_command.gsub!(/\n/, "")
1211
+ # jssh_socket.send("#{jssh_command}\n", 0)
1212
+ # read_socket()
1213
+ # else
1214
+ # jssh_socket.send("#{element_object}.#{event.downcase}();\n", 0)
1215
+ # read_socket()
1216
+ # end
1217
+ # end
1218
+ # else
1219
+ # jssh_command = "#{@@current_js_object.element_name}.click();\n";
1220
+ # jssh_socket.send("#{jssh_command}", 0)
1221
+ # read_socket()
1222
+ # end
1223
+ # @@current_level = 0
1224
+ # @@current_js_object = nil
1225
+ #end
1226
+ #private :click_js_popup_creator_button
1227
+
1228
+ #
1229
+ # Description:
1230
+ # Gets all the cells of the row of a table.
1231
+ #
1232
+ # Output:
1233
+ # Array of table cell elements.
1234
+ #
1235
+ def get_cells
1236
+ assert_exists
1237
+ #puts "element name in cells is : #{element_object}"
1238
+ if(element_type == "HTMLTableRowElement")
1239
+ jssh_socket.send("#{element_object}.cells.length;\n", 0)
1240
+ length = read_socket.to_i
1241
+ return_array = Array.new(length)
1242
+ for i in 0..length - 1 do
1243
+ return_array[i] = "#{element_object}.cells[#{i}]"
1244
+ end
1245
+ return return_array
1246
+ else
1247
+ puts "The element must be of table row type to execute this function."
1248
+ return nil
1249
+ end
1250
+ end
1251
+ private :get_cells
1252
+
1253
+ #
1254
+ # Description:
1255
+ # Traps all the function calls for an element that is not defined and fires them again
1256
+ # as it is to the jssh. This can be used in case the element supports properties or methods
1257
+ # that are not defined in the corresponding element class or in the base class(Element).
1258
+ #
1259
+ # Input:
1260
+ # methodId - Id of the method that is called.
1261
+ # *args - arguments sent to the methods.
1262
+ #
1263
+ def method_missing(methId, *args)
1264
+ methodName = methId.id2name
1265
+ #puts "method name is : #{methodName}"
1266
+ assert_exists
1267
+ #assert_enabled
1268
+ methodName = "colSpan" if methodName == "colspan"
1269
+ if(methodName =~ /invoke/)
1270
+ jssh_command = "#{element_object}."
1271
+ for i in args do
1272
+ jssh_command << i;
1273
+ end
1274
+ #puts "#{jssh_command}"
1275
+ jssh_socket.send("#{jssh_command};\n", 0)
1276
+ return_value = read_socket()
1277
+ #puts "return value is : #{return_value}"
1278
+ return return_value
1279
+ else
1280
+ #assert_exists
1281
+ #puts "element name is #{element_object}"
1282
+
1283
+ # We get method name with trailing '=' when we try to assign a value to a
1284
+ # property. So just remove the '=' to get the type
1285
+ temp = ""
1286
+ assigning_value = false
1287
+ if(methodName =~ /(.*)=$/)
1288
+ temp = "#{element_object}.#{$1}"
1289
+ assigning_value = true
1290
+ else
1291
+ temp = "#{element_object}.#{methodName}"
1292
+ end
1293
+ #puts "temp is : #{temp}"
1294
+
1295
+ jssh_socket.send("typeof(#{temp});\n", 0)
1296
+ method_type = read_socket()
1297
+ #puts "method_type is : #{method_type}"
1298
+
1299
+ if(assigning_value)
1300
+ if(method_type != "boolean" && args[0].class != Fixnum)
1301
+ args[0].gsub!("\\", "\\"*4)
1302
+ args[0].gsub!("\"", "\\\"")
1303
+ args[0].gsub!("\n","\\n")
1304
+ jssh_command = "#{element_object}.#{methodName}\"#{args[0]}\""
1305
+ else
1306
+ jssh_command = "#{element_object}.#{methodName}#{args[0]}"
1307
+ end
1308
+ #puts "jssh_command is : #{jssh_command}"
1309
+ jssh_socket.send("#{jssh_command};\n", 0)
1310
+ read_socket()
1311
+ return
1312
+ end
1313
+
1314
+ methodName = "#{element_object}.#{methodName}"
1315
+ if(args.length == 0)
1316
+ #puts "In if loop #{methodName}"
1317
+ if(method_type == "function")
1318
+ jssh_command = "#{methodName}();\n"
1319
+ else
1320
+ jssh_command = "#{methodName};\n"
1321
+ end
1322
+ else
1323
+ #puts "In else loop : #{methodName}"
1324
+ jssh_command = "#{methodName}("
1325
+
1326
+ count = 0
1327
+ if args != nil
1328
+ for i in args
1329
+ jssh_command << "," if count != 0
1330
+ if i.kind_of? Numeric
1331
+ jssh_command << i.to_s
1332
+ else
1333
+ jssh_command << "\"#{i.to_s.gsub(/"/,"\\\"")}\""
1334
+ end
1335
+ count = count + 1
1336
+ end
1337
+ end
1338
+
1339
+ jssh_command << ");\n"
1340
+ end
1341
+
1342
+ if(method_type == "boolean")
1343
+ jssh_command = jssh_command.gsub("\"false\"", "false")
1344
+ jssh_command = jssh_command.gsub("\"true\"", "true")
1345
+ end
1346
+ #puts "jssh_command is #{jssh_command}"
1347
+ jssh_socket.send("#{jssh_command}", 0)
1348
+ returnValue = read_socket()
1349
+ #puts "return value is : #{returnValue}"
1350
+
1351
+ @@current_level = 0
1352
+
1353
+ if(method_type == "boolean")
1354
+ return false if(returnValue == "false")
1355
+ return true if(returnValue == "true")
1356
+ elsif(method_type == "number")
1357
+ return returnValue.to_i
1358
+ else
1359
+ return returnValue
1360
+ end
1361
+ end
1362
+ end
1363
+
1364
+ end # Element
1365
1365
  end # FireWatir