firewatir 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1778 +1,1775 @@
1
- =begin
2
- license
3
- ---------------------------------------------------------------------------
4
- Copyright (c) 2006-2007, Angrez Singh
5
-
6
- Redistribution and use in source and binary forms, with or without
7
- modification, are permitted provided that the following conditions are met:
8
-
9
- 1. Redistributions of source code must retain the above copyright notice,
10
- this list of conditions and the following disclaimer.
11
-
12
- 2. Redistributions in binary form must reproduce the above copyright
13
- notice, this list of conditions and the following disclaimer in the
14
- documentation and/or other materials provided with the distribution.
15
-
16
- 3. Neither the names Angrez Singh nor the names of contributors to
17
- this software may be used to endorse or promote products derived from this
18
- software without specific prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
21
- IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
24
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27
- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
- --------------------------------------------------------------------------
32
- (based on BSD Open Source License)
33
- =end
34
-
35
- # Base class for html elements.
36
- # This is not a class that users would normally access.
37
- class Element
38
- include Container
39
- # Number of spaces that separate the property from the value in the to_s method
40
- TO_S_SIZE = 14
41
-
42
- # How to get the nodes using XPath in mozilla.
43
- ORDERED_NODE_ITERATOR_TYPE = 5
44
- # To get the number of nodes returned by the xpath expression
45
- NUMBER_TYPE = 1
46
- # To get single node value
47
- FIRST_ORDERED_NODE_TYPE = 9
48
- # This stores the level to which we have gone finding element inside another element.
49
- # This is just to make sure that every element has unique name in JSSH.
50
- @@current_level = 0
51
- # This stores the name of the element that is about to trigger an Javascript pop up.
52
- #@@current_js_object = nil
53
-
54
- attr_accessor :element_name
55
- #
56
- # Description:
57
- # Creates new instance of element. If argument is not nil and is of type string this
58
- # sets the element_name and element_type property of the object. These properties can
59
- # be accessed using element_object and element_type methods respectively.
60
- #
61
- # Used internally by Firewatir.
62
- #
63
- # Input:
64
- # element - Name of the variable with which the element is referenced in JSSh.
65
- #
66
- def initialize(element, container=nil)
67
- @container = container
68
- @element_name = element
69
- @element_type = element_type
70
- #puts "in initialize "
71
- #puts caller(0)
72
- #if(element != nil && element.class == String)
73
- #@element_name = element
74
- #elsif(element != nil && element.class == Element)
75
- # @o = element
76
- #end
77
-
78
- #puts "@element_name is #{@element_name}"
79
- #puts "@element_type is #{@element_type}"
80
- end
81
-
82
- private
83
- def self.def_wrap(ruby_method_name, ole_method_name = nil)
84
- ole_method_name = ruby_method_name unless ole_method_name
85
- class_eval "def #{ruby_method_name}
86
- assert_exists
87
- # Every element has its name starting from element. If yes then
88
- # use element_name to send the command to jssh. Else its a number
89
- # and we are still searching for element, in this case use doc.all
90
- # array with element_name as index to send command to jssh
91
- #puts element_object.to_s
92
- #if(@element_type == 'HTMLDivElement')
93
- # ole_method_name = 'innerHTML'
94
- #end
95
- $jssh_socket.send('typeof(' + element_object + '.#{ole_method_name});\n', 0)
96
- return_type = read_socket()
97
-
98
- return_value = get_attribute_value(\"#{ole_method_name}\")
99
-
100
- #if(return_value == '' || return_value == \"null\")
101
- # return_value = \"\"
102
- #end
103
-
104
- if(return_type == \"boolean\")
105
- return_value = false if return_value == \"false\"
106
- return_value = true if return_value == \"true\"
107
- end
108
- #puts return_value
109
- @@current_level = 0
110
- return return_value
111
- end"
112
- end
113
-
114
- def get_attribute_value(attribute_name)
115
- #if the attribut name is columnLength get number of cells in first row if rows exist.
116
- if(attribute_name == "columnLength")
117
- $jssh_socket.send("#{element_object}.columns;\n", 0)
118
- rowsLength = read_socket()
119
- if(rowsLength != 0 || rowsLength != "")
120
- $jssh_socket.send("#{element_object}.rows[0].cells.length;\n", 0)
121
- return_value = read_socket()
122
- return return_value
123
- end
124
- end
125
- if(attribute_name == "text")
126
- return text()
127
- end
128
- if(attribute_name == "url" or attribute_name == "href" or attribute_name == "src" or attribute_name == "action" or attribute_name == "name")
129
- $jssh_socket.send("#{element_object}.getAttribute(\"#{attribute_name}\");\n" , 0)
130
- return_value = read_socket()
131
- else
132
- jssh_command = "var attribute = '';
133
- if(#{element_object}.#{attribute_name} != undefined)
134
- attribute = #{element_object}.#{attribute_name};
135
- else
136
- attribute = #{element_object}.getAttribute(\"#{attribute_name}\");
137
- attribute;"
138
- jssh_command.gsub!("\n", "")
139
- $jssh_socket.send("#{jssh_command};\n", 0)
140
- #puts jssh_command
141
- return_value = read_socket()
142
- end
143
- if(attribute_name == "value")
144
- $jssh_socket.send("#{element_object}.tagName;\n", 0)
145
- tagName = read_socket().downcase
146
- $jssh_socket.send("#{element_object}.type;\n", 0)
147
- type = read_socket().downcase
148
-
149
- if(tagName == "button" or type == "image" or type == "submit" or type == "reset" or type == "button")
150
- if(return_value == "" or return_value == "null")
151
- $jssh_socket.send("#{element_object}.innerHTML;\n",0)
152
- return_value = read_socket()
153
- end
154
- end
155
- end
156
- #puts "return value of attribute \"{attribute_name}\" is : #{return_value}"
157
- if(return_value == "null" or return_value == "")
158
- return_value = ""
159
- end
160
-
161
- if(return_value =~ /\[object\s.*\]/)
162
- return ""
163
- else
164
- return return_value
165
- end
166
-
167
- end
168
- private:get_attribute_value
169
-
170
-
171
- #
172
- # Description:
173
- # Returns an array of the properties of an element, in a format to be used by the to_s method.
174
- # additional attributes are returned based on the supplied atributes hash.
175
- # name, type, id, value and disabled attributes are common to all the elements.
176
- # This method is used internally by to_s method.
177
- #
178
- # Output:
179
- # Array with values of the following properties:
180
- # name, type, id, value disabled and the supplied attribues list.
181
- #
182
- def string_creator(attributes = nil)
183
- n = []
184
- n << "name:".ljust(TO_S_SIZE) + get_attribute_value("name")
185
- n << "type:".ljust(TO_S_SIZE) + get_attribute_value("type")
186
- n << "id:".ljust(TO_S_SIZE) + get_attribute_value("id")
187
- n << "value:".ljust(TO_S_SIZE) + get_attribute_value("value")
188
- n << "disabled:".ljust(TO_S_SIZE) + get_attribute_value("disabled")
189
- #n << "style:".ljust(TO_S_SIZE) + get_attribute_value("style")
190
- #n << "class:".ljust(TO_S_SIZE) + get_attribute_value("className")
191
-
192
- if(attributes != nil)
193
- attributes.each do |key,value|
194
- n << "#{key}:".ljust(TO_S_SIZE) + get_attribute_value(value)
195
- end
196
- end
197
- return n
198
- end
199
-
200
- #
201
- # Description:
202
- # Sets and clears the colored highlighting on the currently active element.
203
- #
204
- # Input:
205
- # set_or_clear - this can have following two values
206
- # :set - To set the color of the element.
207
- # :clear - To clear the color of the element.
208
- #
209
- def highlight(set_or_clear)
210
- if set_or_clear == :set
211
- #puts "element_name is : #{element_object}"
212
- jssh_command = " var original_color = #{element_object}.style.background;"
213
- jssh_command += " #{element_object}.style.background = \"#{DEFAULT_HIGHLIGHT_COLOR}\"; original_color;"
214
-
215
- # TODO: Need to change this so that it would work if user sets any other color.
216
- #puts "color is : #{DEFAULT_HIGHLIGHT_COLOR}"
217
- $jssh_socket.send("#{jssh_command}\n", 0)
218
- @original_color = read_socket()
219
-
220
- else # BUG: assumes is :clear, but could actually be anything
221
- begin
222
- $jssh_socket.send("#{element_object}.style.background = \"#{@original_color}\";\n", 0)
223
- read_socket()
224
- rescue
225
- # we could be here for a number of reasons...
226
- # e.g. page may have reloaded and the reference is no longer valid
227
- ensure
228
- @original_color = nil
229
- end
230
- end
231
- end
232
- protected :highlight
233
-
234
- #
235
- # Description:
236
- # Returns array of rows for a given table. Returns nil if calling element is not of table type.
237
- #
238
- # Output:
239
- # Array of row elements in an table or nil
240
- #
241
- def get_rows()
242
- #puts "#{element_object} and #{element_type}"
243
- if(element_type == "HTMLTableElement")
244
- $jssh_socket.send("#{element_object}.rows.length;\n", 0)
245
- length = read_socket().to_i
246
- #puts "The number of rows in the table are : #{no_of_rows}"
247
- return_array = Array.new(length)
248
- for i in 0..length - 1 do
249
- return_array[i] = "#{element_object}.rows[#{i}]"
250
- end
251
- return return_array
252
- else
253
- puts "Trying to access rows for Element of type #{element_type}. Element must be of table type to execute this function."
254
- return nil
255
- end
256
- end
257
- private :get_rows
258
-
259
- #
260
- # Description:
261
- # Locates the element on the page depending upon the parameters passed. Logic for locating the element is written
262
- # in JavaScript and then send to JSSh; so that we don't make small round-trips via socket to JSSh. This is done to
263
- # improve the performance for locating the element.
264
- #
265
- # Input:
266
- # tag - Tag name of the element to be located like "input", "a" etc. This is case insensitive.
267
- # how - The attribute by which you want to locate the element like id, name etc. You can use any attribute-value pair
268
- # that uniquely identifies that element on the page. If there are more that one element that have identical
269
- # attribute-value pair then first element that is found while traversing the DOM will be returned.
270
- # what - The value of the attribute specified by how.
271
- # types - Used if that HTML element to be located has different type like input can be of type image, button etc.
272
- # Default value is nil
273
- # value - This is used only in case of radio buttons where they have same name but different value.
274
- #
275
- # Output:
276
- # Returns nil if unable to locate the element, else return the element.
277
- #
278
- def locate_tagged_element(tag, how, what, types = nil, value = nil)
279
- #puts caller(0)
280
- how = :value if how == :caption
281
- how = :href if how == :url
282
- #puts "current element is : #{@container.class} and tag is #{tag}"
283
- # If there is no current element i.e. element in current context we are searching the whole DOM tree.
284
- # So get all the elements.
285
-
286
- if(types != nil and types.include?("button"))
287
- jssh_command = "var isButtonElement = true;"
288
- else
289
- jssh_command = "var isButtonElement = false;"
290
- end
291
-
292
- # Because in both the below cases we need to get element with respect to document.
293
- # when we locate a frame document is automatically adjusted to point to HTML inside the frame
294
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
295
- #end
296
- #if(@@current_element_object == "")
297
- jssh_command += "var elements_#{tag} = null; elements_#{tag} = #{DOCUMENT_VAR}.getElementsByTagName(\"#{tag}\");"
298
- if(types != nil and (types.include?("textarea") or types.include?("button")) )
299
- jssh_command += "elements_#{tag} = #{DOCUMENT_VAR}.body.getElementsByTagName(\"*\");"
300
- end
301
- # @@has_changed = true
302
- else
303
- #puts "container name is: " + @container.element_name
304
- #locate if defined? locate
305
- #@container.locate
306
- jssh_command += "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
307
- if(types != nil and (types.include?("textarea") or types.include?("button") ) )
308
- jssh_command += "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
309
- end
310
- # @@has_changed = false
311
- end
312
-
313
-
314
- if(types != nil)
315
- jssh_command += "var types = new Array("
316
- count = 0
317
- types.each do |type|
318
- if count == 0
319
- jssh_command += "\"#{type}\""
320
- count += 1
321
- else
322
- jssh_command += ",\"#{type}\""
323
- end
324
- end
325
- jssh_command += ");"
326
- else
327
- jssh_command += "var types = null;"
328
- end
329
- #jssh_command += "var elements = #{element_object}.getElementsByTagName('*');"
330
- jssh_command += "var object_index = 1; var o = null; var element_name = '';"
331
-
332
- if(value == nil)
333
- jssh_command += "var value = null;"
334
- else
335
- jssh_command += "var value = \"#{value}\";"
336
- end
337
- #jssh_command += "elements.length;"
338
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
339
-
340
- jssh_command += "for(var i=0; i<elements_#{tag}.length; i++)
341
- {
342
- if(element_name != \"\") break;
343
- var element = elements_#{tag}[i];"
344
- else
345
- jssh_command += "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
346
- {
347
- if(element_name != \"\") break;
348
- var element = elements_#{@@current_level}_#{tag}[i];"
349
- end
350
-
351
- # Because in IE for button the value of "value" attribute also corresponds to the innerHTML if value attribute
352
- # is not supplied. For e.g.: <button>Sign In</button>, in this case value of "value" attribute is "Sign In"
353
- # though value attribute is not supplied. But for Firefox value of "value" attribute is null. So to make sure
354
- # script runs on both IE and Watir we are also considering innerHTML if element is of button type.
355
- jssh_command += " var attribute = '';
356
- var same_type = false;
357
- if(types)
358
- {
359
- for(var j=0; j<types.length; j++)
360
- {
361
- if(types[j] == element.type || types[j] == element.tagName)
362
- {
363
- same_type = true;
364
- break;
365
- }
366
- }
367
- }
368
- else
369
- {
370
- same_type = true;
371
- }
372
- if(same_type == true)
373
- {
374
- if(\"index\" == \"#{how}\")
375
- {
376
- attribute = object_index; object_index += 1;
377
- }
378
- else
379
- {
380
- if(\"text\" == \"#{how}\")
381
- {
382
- attribute = element.textContent;
383
- }
384
- else
385
- {
386
- if(\"#{how}\" == \"href\" || \"#{how}\" == \"src\" || \"#{how}\" == \"action\" || \"#{how}\" == \"name\")
387
- {
388
- attribute = element.getAttribute(\"#{how}\");
389
- }
390
- else
391
- {
392
- if(element.#{how} != undefined)
393
- attribute = element.#{how};
394
- else
395
- attribute = element.getAttribute(\"#{how}\");
396
- }
397
- }
398
- if(\"value\" == \"#{how}\" && isButtonElement && (attribute == null || attribute == ''))
399
- {
400
- attribute = element.innerHTML;
401
- }
402
- }
403
- if(attribute == \"\") o = 'NoMethodError';
404
- var found = false;"
405
-
406
- if(what.class == Regexp)
407
- # Construct the regular expression because we can't use it directly by converting it to string.
408
- # If reg ex is /Google/i then its string conversion will be (?i-mx:Google) so we can't use it.
409
- # Construct the regular expression again from the string conversion.
410
- oldRegExp = what.to_s
411
- newRegExp = "/" + what.source + "/"
412
- flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
413
-
414
- for i in 0..flags.length do
415
- flag = flags[i, 1]
416
- if(flag == '-')
417
- break;
418
- else
419
- newRegExp << flag
420
- end
421
- end
422
- #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
423
- jssh_command += " var regExp = new RegExp(#{newRegExp});
424
- found = regExp.test(attribute);"
425
- elsif(how == :index)
426
- jssh_command += " found = (attribute == #{what});"
427
- else
428
- jssh_command += " found = (attribute == \"#{what}\");"
429
- end
430
- #jssh_command += " found;"
431
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
432
- jssh_command += " if(found)
433
- {
434
- if(value)
435
- {
436
- if(element.value == \"#{value}\")
437
- {
438
- o = element;
439
- element_name = \"elements_#{tag}[\" + i + \"]\";
440
- break;
441
- }
442
- }
443
- else
444
- {
445
- o = element;
446
- element_name = \"elements_#{tag}[\" + i + \"]\";
447
- break;
448
- }
449
- }"
450
- else
451
- jssh_command += " if(found)
452
- {
453
- if(value)
454
- {
455
- if(element.value == \"#{value}\")
456
- {
457
- o = element;
458
- element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
459
- break;
460
- }
461
- }
462
- else
463
- {
464
- o = element;
465
- element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
466
- break;
467
- }
468
- }"
469
- end
470
- jssh_command +=" }
471
- }
472
- element_name;"
473
- # Remove \n that are there in the string as a result of pressing enter while formatting.
474
- jssh_command.gsub!(/\n/, "")
475
- #puts jssh_command
476
- $jssh_socket.send("#{jssh_command};\n", 0)
477
- element_name = read_socket();
478
- #puts "element name in find control is : #{element_name}"
479
- @@current_level = @@current_level + 1
480
- #puts @container
481
- #puts element_name
482
- if(element_name != "")
483
- return element_name #Element.new(element_name, @container)
484
- else
485
- return nil
486
- end
487
- end
488
-
489
- #
490
- # Description:
491
- # Locates frame element. Logic for locating the frame is written in JavaScript so that we don't make small
492
- # round trips to JSSh using socket. This is done to improve the performance for locating the element.
493
- #
494
- # Input:
495
- # how - The attribute for locating the frame. You can use any attribute-value pair that uniquely identifies
496
- # the frame on the page. If there are more than one frames that have identical attribute-value pair
497
- # then first frame that is found while traversing the DOM will be returned.
498
- # what - Value of the attribute specified by how
499
- #
500
- # Output:
501
- # Nil if unable to locate frame, else return the Frame element.
502
- #
503
- def locate_frame(how, what)
504
- # Get all the frames the are there on the page.
505
- #puts "how is #{how} and what is #{what}"
506
- jssh_command = ""
507
- if(@container.class == FireWatir::Firefox)
508
- jssh_command = "var frameset = #{WINDOW_VAR}.frames;
509
- var elements_frames = new Array();
510
- for(var i = 0; i < frameset.length; i++)
511
- {
512
- var frames = frameset[i].frames;
513
- for(var j = 0; j < frames.length; j++)
514
- {
515
- elements_frames.push(frames[j].frameElement);
516
- }
517
- }"
518
- else
519
- jssh_command = "var frames = #{@container.element_name}.contentWindow.frames;
520
- var elements_frames_#{@@current_level} = new Array();
521
- for(var i = 0; i < frames.length; i++)
522
- {
523
- elements_frames_#{@@current_level}.push(frames[i].frameElement);
524
- }"
525
- end
526
-
527
- jssh_command +=" var element_name = ''; var object_index = 1;var attribute = '';
528
- var element = '';"
529
- if(@container.class == FireWatir::Firefox)
530
- jssh_command += "for(var i = 0; i < elements_frames.length; i++)
531
- {
532
- element = elements_frames[i];"
533
- else
534
- jssh_command += "for(var i = 0; i < elements_frames_#{@@current_level}.length; i++)
535
- {
536
- element = elements_frames_#{@@current_level}[i];"
537
- end
538
- jssh_command += " if(\"index\" == \"#{how}\")
539
- {
540
- attribute = object_index; object_index += 1;
541
- }
542
- else
543
- {
544
- attribute = element.getAttribute(\"#{how}\");
545
- if(attribute == \"\" || attribute == null)
546
- {
547
- attribute = element.#{how};
548
- }
549
- }
550
- var found = false;"
551
- if(what.class == Regexp)
552
- # Construct the regular expression because we can't use it directly by converting it to string.
553
- # If reg ex is /Google/i then its string conversion will be (?i-mx:Google) so we can't use it.
554
- # Construct the regular expression again from the string conversion.
555
- oldRegExp = what.to_s
556
- newRegExp = "/" + what.source + "/"
557
- flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
558
-
559
- for i in 0..flags.length do
560
- flag = flags[i, 1]
561
- if(flag == '-')
562
- break;
563
- else
564
- newRegExp << flag
565
- end
566
- end
567
- #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
568
- jssh_command += " var regExp = new RegExp(#{newRegExp});
569
- found = regExp.test(attribute);"
570
- elsif(how == :index)
571
- jssh_command += " found = (attribute == #{what});"
572
- else
573
- jssh_command += " found = (attribute == \"#{what}\");"
574
- end
575
-
576
- jssh_command += " if(found)
577
- {"
578
- if(@container.class == FireWatir::Firefox)
579
- jssh_command += " element_name = \"elements_frames[\" + i + \"]\";
580
- #{DOCUMENT_VAR} = elements_frames[i].contentDocument;
581
- #{BODY_VAR} = #{DOCUMENT_VAR}.body;"
582
- else
583
- jssh_command += " element_name = \"elements_frames_#{@@current_level}[\" + i + \"]\";
584
- #{DOCUMENT_VAR} = elements_frames_#{@@current_level}[i].contentDocument;
585
- #{BODY_VAR} = #{DOCUMENT_VAR}.body;"
586
- end
587
- jssh_command += " break;
588
- }
589
- }
590
- element_name;"
591
-
592
- jssh_command.gsub!("\n", "")
593
- #puts "jssh_command for finding frame is : #{jssh_command}"
594
-
595
- $jssh_socket.send("#{jssh_command};\n", 0)
596
- element_name = read_socket()
597
- @@current_level = @@current_level + 1
598
- #puts "element_name for frame is : #{element_name}"
599
-
600
- if(element_name != "")
601
- return element_name
602
- else
603
- return nil
604
- end
605
- end
606
-
607
- def get_frame_html
608
- $jssh_socket.send("var htmlelem = #{DOCUMENT_VAR}.getElementsByTagName('html')[0]; htmlelem.innerHTML;\n", 0)
609
- #$jssh_socket.send("#{BODY_VAR}.innerHTML;\n", 0)
610
- result = read_socket()
611
- return "<html>" + result + "</html>"
612
- end
613
-
614
- def submit_form
615
- #puts "form name is : #{element_object}"
616
- $jssh_socket.send("#{element_object}.submit();\n" , 0)
617
- read_socket()
618
- end
619
-
620
- public
621
-
622
- #
623
- #
624
- # Description:
625
- # Matches the given text with the current text shown in the browser for that particular element.
626
- #
627
- # Input:
628
- # target - Text to match. Can be a string or regex
629
- #
630
- # Output:
631
- # Returns the index if the specified text was found.
632
- # Returns matchdata object if the specified regexp was found.
633
- #
634
- def contains_text(target)
635
- #puts "Text to match is : #{match_text}"
636
- #puts "Html is : #{self.text}"
637
- if target.kind_of? Regexp
638
- self.text.match(target)
639
- elsif target.kind_of? String
640
- self.text.index(target)
641
- else
642
- raise ArgumentError, "Argument #{target} should be a string or regexp."
643
- end
644
- end
645
- #
646
- # Description:
647
- # Method for inspecting the object. Defined here because IRB was not able to locate the object.
648
- # TODO: Need to find out why IRB is unable to find object though both (this and IRB) are executing same statements
649
- #
650
- def inspect
651
- assert_exists
652
- puts self.to_s
653
- end
654
-
655
- #
656
- # Description:
657
- # Returns array of elements that matches a given XPath query.
658
- # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
659
- # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
660
- # Used internally by Firewatir use ff.elements_by_xpath instead.
661
- #
662
- # Input:
663
- # xpath - The xpath expression or query.
664
- #
665
- # Output:
666
- # Array of elements that matched the xpath expression provided as parameter.
667
- #
668
- def elements_by_xpath(container, xpath)
669
- rand_no = rand(1000)
670
- #jssh_command = "var xpathResult = #{DOCUMENT_VAR}.evaluate(\"count(#{xpath})\", #{DOCUMENT_VAR}, null, #{NUMBER_TYPE}, null); xpathResult.numberValue;"
671
- #$jssh_socket.send("#{jssh_command}\n", 0);
672
- #node_count = read_socket()
673
-
674
- jssh_command = "var element_xpath_#{rand_no} = new Array();"
675
-
676
- jssh_command += "var result = #{DOCUMENT_VAR}.evaluate(\"#{xpath}\", #{DOCUMENT_VAR}, null, #{ORDERED_NODE_ITERATOR_TYPE}, null);
677
- var iterate = result.iterateNext();
678
- while(iterate)
679
- {
680
- element_xpath_#{rand_no}.push(iterate);
681
- iterate = result.iterateNext();
682
- }
683
- element_xpath_#{rand_no}.length;
684
- "
685
-
686
- # Remove \n that are there in the string as a result of pressing enter while formatting.
687
- jssh_command.gsub!(/\n/, "")
688
- #puts jssh_command
689
- $jssh_socket.send("#{jssh_command};\n", 0)
690
- node_count = read_socket()
691
- #puts "value of count is : #{node_count}"
692
-
693
- elements = Array.new(node_count.to_i)
694
-
695
- for i in 0..elements.length - 1 do
696
- elements[i] = "element_xpath_#{rand_no}[#{i}]"
697
- end
698
-
699
- return elements;
700
- end
701
-
702
- #
703
- # Description:
704
- # Returns first element found while traversing the DOM; that matches an given XPath query.
705
- # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
706
- # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
707
- # Used internally by Firewatir use ff.element_by_xpath instead.
708
- #
709
- # Input:
710
- # xpath - The xpath expression or query.
711
- #
712
- # Output:
713
- # First element in DOM that matched the XPath expression or query.
714
- #
715
- def element_by_xpath(container, xpath)
716
- #puts "here locating element by xpath"
717
- rand_no = rand(1000)
718
- jssh_command = "var element_xpath_#{rand_no} = null; element_xpath_#{rand_no} = #{DOCUMENT_VAR}.evaluate(\"#{xpath}\", #{DOCUMENT_VAR}, null, #{FIRST_ORDERED_NODE_TYPE}, null).singleNodeValue; element_xpath_#{rand_no};"
719
-
720
- $jssh_socket.send("#{jssh_command}\n", 0)
721
- result = read_socket()
722
- #puts "command send to jssh is : #{jssh_command}"
723
- #puts "result is : #{result}"
724
- if(result == "null" || result == "" || result.include?("exception"))
725
- @@current_level = 0
726
- return nil
727
- else
728
- @@current_level += 1
729
- return "element_xpath_#{rand_no}"
730
- end
731
- end
732
-
733
- #
734
- # Description:
735
- # Returns the name of the element with which we can access it in JSSh.
736
- # Used internally by Firewatir to execute methods, set properties or return property value for the element.
737
- #
738
- # Output:
739
- # Name of the variable with which element is referenced in JSSh
740
- #
741
- def element_object
742
- #puts caller.join("\n")
743
- #puts "In element_object element name is : #{@element_name}"
744
- #puts "in element_object : #{@container.class}"
745
- #if(@container.class == FireWatir::Firefox)
746
- return @element_name #if @element_name != nil
747
- #else
748
- # return @container.element_name
749
- #end
750
- #return @o.element_name if @o != nil
751
- end
752
- private :element_object
753
-
754
- #
755
- # Description:
756
- # Returns the type of element. For e.g.: HTMLAnchorElement. used internally by Firewatir
757
- #
758
- # Output:
759
- # Type of the element.
760
- #
761
- def element_type
762
- #puts "in element_type object is : #{element_object}"
763
- # Get the type of the element.
764
- $jssh_socket.send("#{element_object};\n", 0)
765
- temp = read_socket()
766
-
767
- if temp == ""
768
- return nil
769
- end
770
-
771
- #puts "#{element_object} and type is #{temp}"
772
- temp =~ /\[object\s(.*)\]/
773
- if $1
774
- return $1
775
- else
776
- # This is done because in JSSh if you write element name of anchor type
777
- # then it displays the link to which it navigates instead of displaying
778
- # object type. So above regex match will return nil
779
- return "HTMLAnchorElement"
780
- end
781
- end
782
- #private :element_type
783
-
784
- #
785
- # Description:
786
- # Fires the provided event for an element and by default waits for the action to get completed.
787
- #
788
- # Input:
789
- # event - Event to be fired like "onclick", "onchange" etc.
790
- # wait - Whether to wait for the action to get completed or not. By default its true.
791
- #
792
- # TODO: Provide ability to specify event parameters like keycode for key events, and click screen
793
- # coordinates for mouse events.
794
- def fire_event(event, wait = true)
795
- assert_exists()
796
- event = event.to_s # in case event was given as a symbol
797
-
798
- event = event.downcase
799
-
800
- event =~ /on(.*)/i
801
- event = $1 if $1
802
-
803
- # check if we've got an old-school on-event
804
- #$jssh_socket.send("typeof(#{element_object}.#{event});\n", 0)
805
- #is_defined = read_socket()
806
-
807
- # info about event types harvested from:
808
- # http://www.howtocreate.co.uk/tutorials/javascript/domevents
809
- case event
810
- when 'abort', 'blur', 'change', 'error', 'focus', 'load', 'reset', 'resize',
811
- 'scroll', 'select', 'submit', 'unload'
812
- dom_event_type = 'HTMLEvents'
813
- dom_event_init = "initEvent(\"#{event}\", true, true)"
814
- when 'keydown', 'keypress', 'keyup'
815
- dom_event_type = 'KeyEvents'
816
- # Firefox has a proprietary initializer for keydown/keypress/keyup.
817
- # Args are as follows:
818
- # 'type', bubbles, cancelable, windowObject, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
819
- dom_event_init = "initKeyEvent(\"#{event}\", true, true, #{WINDOW_VAR}, false, false, false, false, 0, 0)"
820
- when 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover',
821
- 'mouseup'
822
- dom_event_type = 'MouseEvents'
823
- # Args are as follows:
824
- # 'type', bubbles, cancelable, windowObject, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget
825
- dom_event_init = "initMouseEvent(\"#{event}\", true, true, #{WINDOW_VAR}, 1, 0, 0, 0, 0, false, false, false, false, 0, null)"
826
- else
827
- dom_event_type = 'HTMLEvents'
828
- dom_event_init = "initEvents(\"#{event}\", true, true)"
829
- end
830
-
831
- if(element_type == "HTMLSelectElement")
832
- dom_event_type = 'HTMLEvents'
833
- dom_event_init = "initEvent(\"#{event}\", true, true)"
834
- end
835
-
836
-
837
- jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"#{dom_event_type}\"); "
838
- jssh_command << "event.#{dom_event_init}; "
839
- jssh_command << "#{element_object}.dispatchEvent(event);"
840
-
841
- #puts "JSSH COMMAND:\n#{jssh_command}\n"
842
-
843
- $jssh_socket.send("#{jssh_command}\n", 0)
844
- read_socket() if wait
845
- wait() if wait
846
-
847
- @@current_level = 0
848
- end
849
- alias fireEvent fire_event
850
-
851
- #
852
- # Description:
853
- # Returns the value of the specified attribute of an element.
854
- #
855
- def attribute_value(attribute_name)
856
- #puts attribute_name
857
- assert_exists()
858
- return_value = get_attribute_value(attribute_name)
859
- @@current_level = 0
860
- return return_value
861
- end
862
-
863
- #
864
- # Description:
865
- # Checks if element exists or not. Raises UnknownObjectException if element doesn't exists.
866
- #
867
- def assert_exists
868
- unless exists?
869
- raise UnknownObjectException.new("Unable to locate object, using #{@how} and #{@what}")
870
- end
871
- end
872
-
873
- #
874
- # Description:
875
- # Checks if element is enabled or not. Raises ObjectDisabledException if object is disabled and
876
- # you are trying to use the object.
877
- #
878
- def assert_enabled
879
- unless enabled?
880
- raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
881
- end
882
- end
883
-
884
- #
885
- # Description:
886
- # First checks if element exists or not. Then checks if element is enabled or not.
887
- #
888
- # Output:
889
- # Returns true if element exists and is enabled, else returns false.
890
- #
891
- def enabled?
892
- assert_exists
893
- $jssh_socket.send("#{element_object}.disabled;\n", 0)
894
- value = read_socket()
895
- @@current_level = 0
896
- return true if(value == "false")
897
- return false if(value == "true")
898
- return value
899
- end
900
-
901
- #
902
- # Description:
903
- # Checks if element exists or not. If element is not located yet then first locates the element.
904
- #
905
- # Output:
906
- # True if element exists, false otherwise.
907
- #
908
- def exists?
909
- #puts "element is : #{element_object}"
910
- # If elements array has changed locate the element again. So that the element name points to correct element.
911
- if(element_object == nil || element_object == "")
912
- #puts "locating element"
913
- locate if defined?(locate)
914
- if(@element_name == nil || @element_name == "")
915
- return false
916
- else
917
- #puts caller(0)
918
- #puts "element name is : #{@element_name}"
919
- return true
920
- end
921
- else
922
- #puts "not locating the element again"
923
- return true
924
- end
925
- @@current_level = 0
926
- if(element_object == nil || element_object == "")
927
- return false
928
- else
929
- return true
930
- end
931
- end
932
-
933
- #
934
- # Description:
935
- # Returns the text of the element.
936
- #
937
- # Output:
938
- # Text of the element.
939
- #
940
- def text()
941
- assert_exists
942
-
943
- if(element_type == "HTMLFrameElement")
944
- $jssh_socket.send("#{BODY_VAR}.textContent;\n", 0)
945
- else
946
- $jssh_socket.send("#{element_object}.textContent;\n", 0)
947
- end
948
-
949
- return_value = read_socket().strip()
950
- #puts "text content of element is : #{return_value}"
951
-
952
- #if(returnType == "boolean")
953
- # return_value = false if returnValue == "false"
954
- # return_value = true if returnValue == "true"
955
- #end
956
- @@current_level = 0
957
- return return_value
958
- end
959
- alias innerText text
960
-
961
- # Returns the name of the element (as defined in html)
962
- def_wrap :name
963
- # Returns the id of the element
964
- def_wrap :id
965
- # Returns whether the element is disabled
966
- def_wrap :disabled
967
- alias disabled? disabled
968
- # Returns the state of the element
969
- def_wrap :checked
970
- # Returns the value of the element
971
- def_wrap :value
972
- # Returns the title of the element
973
- def_wrap :title
974
- # Returns the value of 'alt' attribute in case of Image element.
975
- def_wrap :alt
976
- # Returns the value of 'href' attribute in case of Anchor element.
977
- def_wrap :src
978
- # Returns the type of the element. Use in case of Input element only.
979
- def_wrap :type
980
- # Returns the url the Anchor element points to.
981
- def_wrap :href
982
- # Return the ID of the control that this label is associated with
983
- def_wrap :for, :htmlFor
984
- # Returns the class name of the element
985
- def_wrap :class_name, :className
986
- # Return the html of the object
987
- def_wrap :html, :innerHTML
988
- # Return the action of form
989
- def_wrap :action
990
-
991
- #
992
- # Description:
993
- # Display basic details about the object. Sample output for a button is shown.
994
- # Raises UnknownObjectException if the object is not found.
995
- # name b4
996
- # type button
997
- # id b5
998
- # value Disabled Button
999
- # disabled true
1000
- #
1001
- # Output:
1002
- # Array with value of properties shown above.
1003
- #
1004
- def to_s(attributes=nil)
1005
- #puts "here in to_s"
1006
- #puts caller(0)
1007
- assert_exists
1008
- if(element_type == "HTMLTableCellElement")
1009
- return text()
1010
- else
1011
- result = string_creator(attributes) #.join("\n")
1012
- @@current_level = 0
1013
- return result
1014
- end
1015
- end
1016
-
1017
- #
1018
- # Description:
1019
- # Function to fire click event on elements.
1020
- #
1021
- def click
1022
- assert_exists
1023
- assert_enabled
1024
-
1025
- highlight(:set)
1026
- #puts "#{element_object} and #{element_type}"
1027
- case element_type
1028
-
1029
- when "HTMLAnchorElement", "HTMLImageElement"
1030
- # Special check for link or anchor tag. Because click() doesn't work on links.
1031
- # More info: http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-48250443
1032
- # https://bugzilla.mozilla.org/show_bug.cgi?id=148585
1033
-
1034
- jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"MouseEvents\");"
1035
-
1036
- # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1037
- jssh_command += "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1038
- jssh_command += "#{element_object}.dispatchEvent(event);\n"
1039
-
1040
- #puts "jssh_command is: #{jssh_command}"
1041
- $jssh_socket.send("#{jssh_command}", 0)
1042
- read_socket()
1043
- else
1044
- $jssh_socket.send("typeof(#{element_object}.click);\n", 0)
1045
- isDefined = read_socket()
1046
- if(isDefined == "undefined")
1047
- fire_event("onclick")
1048
- else
1049
- $jssh_socket.send("#{element_object}.click();\n" , 0)
1050
- read_socket()
1051
- end
1052
- end
1053
- highlight(:clear)
1054
- # Wait for firefox to reload.
1055
- wait()
1056
- end
1057
-
1058
- #
1059
- # Description:
1060
- # Wait for the browser to get loaded, after the event is being fired.
1061
- #
1062
- def wait
1063
- #ff = FireWatir::Firefox.new
1064
- #ff.wait()
1065
- #puts @container
1066
- @container.wait()
1067
- @@current_level = 0
1068
- end
1069
-
1070
- #
1071
- # Description:
1072
- # Function is used for click events that generates javascript pop up.
1073
- # Doesn't fire the click event immediately instead, it stores the state of the object. User then tells which button
1074
- # is to be clicked in case a javascript pop up comes after clicking the element. Depending upon the button to be clicked
1075
- # the functions 'alert' and 'confirm' are re-defined in JavaScript to return appropriate values either true or false. Then the
1076
- # re-defined functions are send to jssh which then fires the click event of the element using the state
1077
- # stored above. So the click event is fired in the second statement. Therefore, if you are using this function you
1078
- # need to call 'click_js_popup_button()' function in the next statement to actually trigger the click event.
1079
- #
1080
- # Typical Usage:
1081
- # ff.button(:id, "button").click_no_wait()
1082
- # ff.click_js_popup_button("OK")
1083
- #
1084
- #def click_no_wait
1085
- # assert_exists
1086
- # assert_enabled
1087
- #
1088
- # highlight(:set)
1089
- # @@current_js_object = Element.new("#{element_object}", @container)
1090
- #end
1091
-
1092
- #
1093
- # Description:
1094
- # Function to click specified button on the javascript pop up. Currently you can only click
1095
- # either OK or Cancel button.
1096
- # Functions alert and confirm are redefined so that it doesn't causes the JSSH to get blocked. Also this
1097
- # will make Firewatir cross platform.
1098
- #
1099
- # Input:
1100
- # button to be clicked
1101
- #
1102
- #def click_js_popup(button = "OK")
1103
- # jssh_command = "var win = #{BROWSER_VAR}.contentWindow;"
1104
- # if(button =~ /ok/i)
1105
- # jssh_command += "var popuptext = '';win.alert = function(param) {popuptext = param; return true; };
1106
- # win.confirm = function(param) {popuptext = param; return true; };"
1107
- # elsif(button =~ /cancel/i)
1108
- # jssh_command += "var popuptext = '';win.alert = function(param) {popuptext = param; return false; };
1109
- # win.confirm = function(param) {popuptext = param; return false; };"
1110
- # end
1111
- # jssh_command.gsub!(/\n/, "")
1112
- # $jssh_socket.send("#{jssh_command}\n", 0)
1113
- # read_socket()
1114
- # click_js_popup_creator_button()
1115
- # #$jssh_socket.send("popuptext_alert;\n", 0)
1116
- # #read_socket()
1117
- # $jssh_socket.send("\n", 0)
1118
- # read_socket()
1119
- #end
1120
-
1121
- #
1122
- # Description:
1123
- # Clicks on button or link or any element that triggers a javascript pop up.
1124
- # Used internally by function click_js_popup.
1125
- #
1126
- #def click_js_popup_creator_button
1127
- # #puts @@current_js_object.element_name
1128
- # $jssh_socket.send("#{@@current_js_object.element_name}\n;", 0)
1129
- # temp = read_socket()
1130
- # temp =~ /\[object\s(.*)\]/
1131
- # if $1
1132
- # type = $1
1133
- # else
1134
- # # This is done because in JSSh if you write element name of anchor type
1135
- # # then it displays the link to which it navigates instead of displaying
1136
- # # object type. So above regex match will return nil
1137
- # type = "HTMLAnchorElement"
1138
- # end
1139
- # #puts type
1140
- # case type
1141
- # when "HTMLAnchorElement", "HTMLImageElement"
1142
- # jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"MouseEvents\");"
1143
- # # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1144
- # jssh_command += "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1145
- # jssh_command += "#{@@current_js_object.element_name}.dispatchEvent(event);\n"
1146
- #
1147
- # $jssh_socket.send("#{jssh_command}", 0)
1148
- # read_socket()
1149
- # when "HTMLDivElement", "HTMLSpanElement"
1150
- # $jssh_socket.send("typeof(#{element_object}.#{event.downcase});\n", 0)
1151
- # isDefined = read_socket()
1152
- # #puts "is method there : #{isDefined}"
1153
- # if(isDefined != "undefined")
1154
- # if(element_type == "HTMLSelectElement")
1155
- # jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"HTMLEvents\");
1156
- # event.initEvent(\"click\", true, true);
1157
- # #{element_object}.dispatchEvent(event);"
1158
- # jssh_command.gsub!(/\n/, "")
1159
- # $jssh_socket.send("#{jssh_command}\n", 0)
1160
- # read_socket()
1161
- # else
1162
- # $jssh_socket.send("#{element_object}.#{event.downcase}();\n", 0)
1163
- # read_socket()
1164
- # end
1165
- # end
1166
- # else
1167
- # jssh_command = "#{@@current_js_object.element_name}.click();\n";
1168
- # $jssh_socket.send("#{jssh_command}", 0)
1169
- # read_socket()
1170
- # end
1171
- # @@current_level = 0
1172
- # @@current_js_object = nil
1173
- #end
1174
- #private :click_js_popup_creator_button
1175
-
1176
- #
1177
- # Description:
1178
- # Gets all the options of the select list element.
1179
- #
1180
- # Output:
1181
- # Array of option elements.
1182
- #
1183
- def options
1184
- $jssh_socket.send("#{element_object}.options.length;\n", 0)
1185
- length = read_socket().to_i
1186
- #puts "options length is : #{length}"
1187
- arr_options = Array.new(length)
1188
- for i in 0..length - 1
1189
- arr_options[i] = "#{element_object}.options[#{i}]"
1190
- end
1191
- return arr_options
1192
- end
1193
- private :options
1194
-
1195
- #
1196
- # Description:
1197
- # Used to get class name for option element. Used internally by Firewatir use ff.select_list(...).option(..).class
1198
- #
1199
- # Output:
1200
- # Class name of option element.
1201
- #
1202
- def option_class_name
1203
- $jssh_socket.send("#{element_object}.className;\n", 0)
1204
- return read_socket()
1205
- end
1206
- private :option_class_name
1207
-
1208
- #
1209
- # Description:
1210
- # Used to get text for option element. Used internally by Firewatir use ff.select_list(...).option(..).text
1211
- #
1212
- # Output:
1213
- # Text of option element.
1214
- #
1215
- def option_text
1216
- $jssh_socket.send("#{element_object}.text;\n", 0)
1217
- return read_socket()
1218
- end
1219
- private :option_text
1220
-
1221
- #
1222
- # Description:
1223
- # Used to get value for option element. Used internally by Firewatir use ff.select_list(...).option(..).value
1224
- #
1225
- # Output:
1226
- # Value of option element.
1227
- #
1228
- def option_value
1229
- $jssh_socket.send("#{element_object}.value;\n", 0)
1230
- return read_socket()
1231
- end
1232
- private :option_value
1233
-
1234
- #
1235
- # Description:
1236
- # Used to check if option is selected or not. Used internally by Firewatir use ff.select_list(...).option(..).selected
1237
- #
1238
- # Output:
1239
- # True if option is selected, false otherwise.
1240
- #
1241
- def option_selected
1242
- $jssh_socket.send("#{element_object}.selected;\n", 0)
1243
- value = read_socket()
1244
- return true if value == "true"
1245
- return false if value == "false"
1246
- end
1247
- private :option_selected
1248
-
1249
- #
1250
- # Description:
1251
- # Gets all the cells of the row of a table.
1252
- #
1253
- # Output:
1254
- # Array of table cell elements.
1255
- #
1256
- def get_cells
1257
- assert_exists
1258
- #puts "element name in cells is : #{element_object}"
1259
- if(element_type == "HTMLTableRowElement")
1260
- $jssh_socket.send("#{element_object}.cells.length;\n", 0)
1261
- length = read_socket.to_i
1262
- return_array = Array.new(length)
1263
- for i in 0..length - 1 do
1264
- return_array[i] = "#{element_object}.cells[#{i}]"
1265
- end
1266
- return return_array
1267
- else
1268
- puts "The element must be of table row type to execute this function."
1269
- return nil
1270
- end
1271
- end
1272
- private :get_cells
1273
-
1274
- #
1275
- # Description:
1276
- # Sets the value of file in HTMLInput file field control.
1277
- #
1278
- # Input:
1279
- # setPath - location of the file to be uploaded. '|' should not be part of filename.
1280
- #
1281
- def setFileFieldValue(setPath)
1282
- # As ruby converts \\ to \ and while sending name to jssh \ is ignored.
1283
- # So replace \ with \\. Now this is even trickier you can't replace \ with \\
1284
- # directly like this string.gsub!("\\", "\\\\") this doesn't work.
1285
- # Work around is replace '\' with two special character and then replace
1286
- # special character with \.
1287
- setPath.gsub!("\\", "||")
1288
- setPath.gsub!("|", "\\")
1289
-
1290
- #jssh_command = "var textBox = #{DOCUMENT_VAR}.getBoxObjectFor(#{element_object}).firstChild;"
1291
- #jssh_command += "textBox.value = \"#{setPath}\";\n";
1292
-
1293
- #puts jssh_command
1294
- $jssh_socket.send("#{element_object}.value = \"#{setPath}\";\n", 0)
1295
- read_socket()
1296
- @@current_level = 0
1297
- end
1298
- private :setFileFieldValue
1299
-
1300
- #
1301
- # Description:
1302
- # Traps all the function calls for an element that is not defined and fires them again
1303
- # as it is to the jssh. This can be used in case the element supports properties or methods
1304
- # that are not defined in the corresponding element class or in the base class(Element).
1305
- #
1306
- # Input:
1307
- # methodId - Id of the method that is called.
1308
- # *args - arguments sent to the methods.
1309
- #
1310
- def method_missing(methId, *args)
1311
- methodName = methId.id2name
1312
- #puts "method name is : #{methodName}"
1313
- assert_exists
1314
- #assert_enabled
1315
- methodName = "colSpan" if methodName == "colspan"
1316
- if(methodName =~ /invoke/)
1317
- jssh_command = "#{element_object}."
1318
- for i in args do
1319
- jssh_command += i;
1320
- end
1321
- #puts "#{jssh_command}"
1322
- $jssh_socket.send("#{jssh_command};\n", 0)
1323
- return_value = read_socket()
1324
- #puts "return value is : #{return_value}"
1325
- return return_value
1326
- else
1327
- #assert_exists
1328
- #puts "element name is #{element_object}"
1329
-
1330
- # We get method name with trailing '=' when we try to assign a value to a
1331
- # property. So just remove the '=' to get the type
1332
- temp = ""
1333
- assingning_value = false
1334
- if(methodName =~ /(.*)=$/)
1335
- temp = "#{element_object}.#{$1}"
1336
- assingning_value = true
1337
- else
1338
- temp = "#{element_object}.#{methodName}"
1339
- end
1340
- #puts "temp is : #{temp}"
1341
-
1342
- $jssh_socket.send("typeof(#{temp});\n", 0)
1343
- method_type = read_socket()
1344
- #puts "method_type is : #{method_type}"
1345
-
1346
- if(assingning_value)
1347
- if(method_type != "boolean" && args[0].class != Fixnum)
1348
- args[0].gsub!("\\", "\\"*4)
1349
- args[0].gsub!("\"", "\\\"")
1350
- args[0].gsub!("\n","\\n")
1351
- jssh_command = "#{element_object}.#{methodName}\"#{args[0]}\""
1352
- else
1353
- jssh_command = "#{element_object}.#{methodName}#{args[0]}"
1354
- end
1355
- #puts "jssh_command is : #{jssh_command}"
1356
- $jssh_socket.send("#{jssh_command};\n", 0)
1357
- read_socket()
1358
- return
1359
- end
1360
-
1361
- methodName = "#{element_object}.#{methodName}"
1362
- if(args.length == 0)
1363
- #puts "In if loop #{methodName}"
1364
- if(method_type == "function")
1365
- jssh_command = "#{methodName}();\n"
1366
- else
1367
- jssh_command = "#{methodName};\n"
1368
- end
1369
- else
1370
- #puts "In else loop : #{methodName}"
1371
- jssh_command = "#{methodName}("
1372
-
1373
- count = 0
1374
- if args != nil
1375
- for i in args
1376
- jssh_command += "," if count != 0
1377
- if i.kind_of? Numeric
1378
- jssh_command += i.to_s
1379
- else
1380
- jssh_command += "\"#{i.to_s.gsub(/"/,"\\\"")}\""
1381
- end
1382
- count = count + 1
1383
- end
1384
- end
1385
-
1386
- jssh_command += ");\n"
1387
- end
1388
-
1389
- if(method_type == "boolean")
1390
- jssh_command = jssh_command.gsub("\"false\"", "false")
1391
- jssh_command = jssh_command.gsub("\"true\"", "true")
1392
- end
1393
- #puts "jssh_command is #{jssh_command}"
1394
- $jssh_socket.send("#{jssh_command}", 0)
1395
- returnValue = read_socket()
1396
- #puts "return value is : #{returnValue}"
1397
-
1398
- @@current_level = 0
1399
-
1400
- if(method_type == "boolean")
1401
- return false if(returnValue == "false")
1402
- return true if(returnValue == "true")
1403
- elsif(method_type == "number")
1404
- return returnValue.to_i
1405
- else
1406
- return returnValue
1407
- end
1408
- end
1409
- end
1410
- end
1411
-
1412
- #
1413
- # Description:
1414
- # Class for returning the document element.
1415
- #
1416
- class Document
1417
- include Container
1418
- @@current_level = 0
1419
-
1420
- #
1421
- # Description:
1422
- # Creates new instance of Document class.
1423
- #
1424
- def initialize(container)
1425
- @length = 0
1426
- @elements = nil
1427
- @arr_elements = ""
1428
- @container = container
1429
- end
1430
-
1431
- #
1432
- # Description:
1433
- # Find all the elements in the document by querying DOM.
1434
- # Set the class variables like length and the variable name of array storing the elements in JSSH.
1435
- #
1436
- # Output:
1437
- # Array of elements.
1438
- #
1439
- def all
1440
- @arr_elements = "arr_coll_#{@@current_level}"
1441
- jssh_command = "var arr_coll_#{@@current_level}=new Array(); "
1442
-
1443
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
1444
- jssh_command +="var element_collection = null; element_collection = #{DOCUMENT_VAR}.getElementsByTagName(\"*\");
1445
- if(element_collection != null && typeof(element_collection) != 'undefined')
1446
- {
1447
- for (var i = 0; i < element_collection.length; i++)
1448
- {
1449
- if((element_collection[i].tagName != 'BR') && (element_collection[i].tagName != 'HR') && (element_collection[i].tagName != 'DOCTYPE') && (element_collection[i].tagName != 'META') && (typeof(element_collection[i].tagName) != 'undefined'))
1450
- arr_coll_#{@@current_level}.push(element_collection[i]);
1451
- }
1452
- }
1453
- arr_coll_#{@@current_level}.length;"
1454
- else
1455
- jssh_command +="var element_collection = null; element_collection = #{@container.element_name}.getElementsByTagName(\"*\");
1456
- if(element_collection!= null && typeof(element_collection) != 'undefined')
1457
- {
1458
- for (var i = 0; i < element_collection.length; i++)
1459
- {
1460
- if((element_collection[i].tagName != 'BR') && (element_collection[i].tagName != 'HR') && (element_collection[i].tagName != 'DOCTYPE') && (element_collection[i].tagName != 'META') && (typeof(element_collection[i].tagName) != 'undefined'))
1461
- arr_coll_#{@@current_level}.push(element_collection[i]);
1462
- }
1463
- }
1464
- arr_coll_#{@@current_level}.length;"
1465
- end
1466
-
1467
- # Remove \n that are there in the string as a result of pressing enter while formatting.
1468
- jssh_command.gsub!(/\n/, "")
1469
- #puts jssh_command
1470
- $jssh_socket.send("#{jssh_command};\n", 0)
1471
- @length = read_socket().to_i;
1472
- #puts "elements length is in locate_tagged_elements is : #{@length}"
1473
-
1474
- elements = nil
1475
- elements = Array.new(@length)
1476
- for i in 0..@length - 1 do
1477
- temp = Element.new("arr_coll_#{@@current_level}[#{i}]", @container)
1478
- elements[i] = temp
1479
- end
1480
- @@current_level += 1
1481
- return elements
1482
-
1483
- end
1484
-
1485
- #
1486
- # Description:
1487
- # Returns the count of elements in the document.
1488
- #
1489
- # Output:
1490
- # Count of elements found in the document.
1491
- #
1492
- def length
1493
- return @length
1494
- end
1495
-
1496
- #
1497
- # Description:
1498
- # Iterates over elements in the document.
1499
- #
1500
- def each
1501
- for i in 0..@length - 1
1502
- yield Element.new("#{@arr_elements}[#{i}]", @container)
1503
- end
1504
- end
1505
-
1506
- #
1507
- # Description:
1508
- # Gets the element at the nth index in the array of the elements.
1509
- #
1510
- # Input:
1511
- # n - Index of element you want to access. Index is 1 based.
1512
- #
1513
- # Output:
1514
- # Element at the nth index.
1515
- #
1516
- def [](n)
1517
- return Element.new("#{@arr_elements}[#{n-1}]", @container)
1518
- end
1519
-
1520
- #
1521
- # Description:
1522
- # Get all forms available on the page.
1523
- # Used internally by Firewatir use ff.show_forms instead.
1524
- #
1525
- # Output:
1526
- # Array containing Form elements
1527
- #
1528
- def get_forms()
1529
- $jssh_socket.send("var element_forms = #{DOCUMENT_VAR}.forms; element_forms.length;\n", 0)
1530
- length = read_socket().to_i
1531
- forms = Array.new(length)
1532
-
1533
- for i in 0..length - 1 do
1534
- forms[i] = Form.new(@container, :jssh_name, "element_forms[#{i}]")
1535
- end
1536
- return forms
1537
- end
1538
-
1539
- #
1540
- # Description:
1541
- # Get all images available on the page.
1542
- # Used internally by Firewatir use ff.show_images instead.
1543
- #
1544
- # Output:
1545
- # Array containing Image elements
1546
- #
1547
- def get_images
1548
- return Images.new(@container)
1549
- end
1550
-
1551
- #
1552
- # Description:
1553
- # Get all links available on the page.
1554
- # Used internally by Firewatir use ff.show_links instead.
1555
- #
1556
- # Output:
1557
- # Array containing Link elements
1558
- #
1559
- def get_links
1560
- return Links.new(@container)
1561
- end
1562
-
1563
- #
1564
- # Description:
1565
- # Get all divs available on the page.
1566
- # Used internally by Firewatir use ff.show_divs instead.
1567
- #
1568
- # Output:
1569
- # Array containing Div elements
1570
- #
1571
- def get_divs
1572
- return Divs.new(@container)
1573
- end
1574
-
1575
- #
1576
- # Description:
1577
- # Get all tables available on the page.
1578
- # Used internally by Firewatir use ff.show_tables instead.
1579
- #
1580
- # Output:
1581
- # Array containing Table elements
1582
- #
1583
- def get_tables
1584
- return Tables.new(@container)
1585
- end
1586
-
1587
- #
1588
- # Description:
1589
- # Get all pres available on the page.
1590
- # Used internally by Firewatir use ff.show_pres instead.
1591
- #
1592
- # Output:
1593
- # Array containing Pre elements
1594
- #
1595
- def get_pres
1596
- return Pres.new(@container)
1597
- end
1598
-
1599
- #
1600
- # Description:
1601
- # Get all spans available on the page.
1602
- # Used internally by Firewatir use ff.show_spans instead.
1603
- #
1604
- # Output:
1605
- # Array containing Span elements
1606
- #
1607
- def get_spans
1608
- return Spans.new(@container)
1609
- end
1610
-
1611
- #
1612
- # Description:
1613
- # Get all labels available on the page.
1614
- # Used internally by Firewatir use ff.show_labels instead.
1615
- #
1616
- # Output:
1617
- # Array containing Label elements
1618
- #
1619
- def get_labels
1620
- return Labels.new(@container)
1621
- end
1622
- end
1623
-
1624
- #
1625
- # Description:
1626
- # Class for iterating over elements of common type like links, images, divs etc.
1627
- #
1628
- class ElementCollections
1629
- include Container
1630
- @@current_level = 0
1631
- #
1632
- # Description:
1633
- # Initializes new instance of this class.
1634
- #
1635
- # Input:
1636
- # tag - tag name of the element for which you want the iterator.
1637
- # types - element type. used in case where same element tag has different types like input has type image, button etc.
1638
- #
1639
- #def initialize(container, tag , types=nil)
1640
- # @@current_level += 1
1641
- # @@current_element_object = Element.get_current_element
1642
- # #puts " the current object #{@@current_element_object}"
1643
- # @length = 0
1644
- # @arr_name = ""
1645
- # @container = container
1646
- # @elements = locate_tagged_elements(tag , types)
1647
- #end
1648
-
1649
- #
1650
- # Description:
1651
- # Locate all the elements of give tag and type.
1652
- #
1653
- # Input:
1654
- # tag - tag name of the element for which you want the iterator.
1655
- # types - element type. used in case where same element tag has different types like input has type image, button etc.
1656
- #
1657
- # Output:
1658
- # Elements array containing all the elements found on the page.
1659
- #
1660
- def locate_tagged_elements(tag , types = nil)
1661
- jssh_command = "var arr_coll_#{tag}_#{@@current_level}=new Array();"
1662
- @arr_name = "arr_coll_#{tag}_#{@@current_level}"
1663
-
1664
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
1665
- jssh_command += "var elements_#{tag} = null; elements_#{tag} = #{DOCUMENT_VAR}.getElementsByTagName(\"#{tag}\");"
1666
- if(types != nil and (types.include?("textarea") or types.include?("button")) )
1667
- jssh_command += "elements_#{tag} = #{DOCUMENT_VAR}.body.getElementsByTagName(\"*\");"
1668
- end
1669
- else
1670
- jssh_command += "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
1671
- if(types != nil and (types.include?("textarea") or types.include?("button")) )
1672
- jssh_command += "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
1673
- end
1674
- end
1675
-
1676
- if(types != nil)
1677
- jssh_command += "var types = new Array("
1678
- count = 0
1679
- types.each do |type|
1680
- if count == 0
1681
- jssh_command += "\"#{type}\""
1682
- count += 1
1683
- else
1684
- jssh_command += ",\"#{type}\""
1685
- end
1686
- end
1687
- jssh_command += ");"
1688
- else
1689
- jssh_command += "var types = null;"
1690
- end
1691
-
1692
- if(@container.class == FireWatir::Firefox || @container.class == Frame)
1693
-
1694
- jssh_command += "for(var i=0; i<elements_#{tag}.length; i++)
1695
- {
1696
-
1697
- var element = elements_#{tag}[i];"
1698
- else
1699
- jssh_command += "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
1700
- {
1701
-
1702
- var element = elements_#{@@current_level}_#{tag}[i];"
1703
- end
1704
-
1705
- jssh_command += "
1706
- var same_type = false;
1707
- if(types)
1708
- {
1709
- for(var j=0; j<types.length; j++)
1710
- {
1711
- if(types[j] == element.type || types[j] == element.tagName)
1712
- {
1713
- same_type = true;
1714
- break;
1715
- }
1716
- }
1717
- }
1718
- else
1719
- {
1720
- same_type = true;
1721
- }
1722
- if(same_type == true)
1723
- {
1724
- arr_coll_#{tag}_#{@@current_level}.push(element);
1725
- }
1726
- }
1727
- arr_coll_#{tag}_#{@@current_level}.length;"
1728
-
1729
- # Remove \n that are there in the string as a result of pressing enter while formatting.
1730
- jssh_command.gsub!(/\n/, "")
1731
- #puts jssh_command
1732
- $jssh_socket.send("#{jssh_command};\n", 0)
1733
- length = read_socket().to_i;
1734
- #puts "elements length is in locate_tagged_elements is : #{length}"
1735
-
1736
- elements = Array.new(length)
1737
- for i in 0..length - 1 do
1738
- elements[i] = "arr_coll_#{tag}_#{@@current_level}[#{i}]"
1739
- end
1740
- @@current_level = @@current_level + 1
1741
- return elements
1742
- end
1743
- private:locate_tagged_elements
1744
-
1745
- #
1746
- # Description:
1747
- # Gets the length of elements of same tag and type found on the page.
1748
- #
1749
- # Ouput:
1750
- # Count of elements found on the page.
1751
- #
1752
- def length
1753
- #puts @element_objects.length
1754
- return @element_objects.length
1755
- end
1756
-
1757
- #
1758
- # Description:
1759
- # Iterate over the elements of same tag and type found on the page.
1760
- #
1761
- def each
1762
- for i in 0..@element_objects.length - 1
1763
- yield @element_objects[i]
1764
- end
1765
- end
1766
-
1767
- #
1768
- # Description:
1769
- # Accesses nth element of same tag and type found on the page.
1770
- #
1771
- # Input:
1772
- # n - index of element (1 based)
1773
- #
1774
- def [](n)
1775
- return @element_objects[n-1]
1776
- end
1777
-
1778
- end
1
+ =begin
2
+ license
3
+ ---------------------------------------------------------------------------
4
+ Copyright (c) 2006-2007, Angrez Singh
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the names Angrez Singh nor the names of contributors to
17
+ this software may be used to endorse or promote products derived from this
18
+ software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
21
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
24
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ --------------------------------------------------------------------------
32
+ (based on BSD Open Source License)
33
+ =end
34
+
35
+ # Base class for html elements.
36
+ # This is not a class that users would normally access.
37
+ class Element
38
+ include Container
39
+ # Number of spaces that separate the property from the value in the to_s method
40
+ TO_S_SIZE = 14
41
+
42
+ # How to get the nodes using XPath in mozilla.
43
+ ORDERED_NODE_ITERATOR_TYPE = 5
44
+ # To get the number of nodes returned by the xpath expression
45
+ NUMBER_TYPE = 1
46
+ # To get single node value
47
+ FIRST_ORDERED_NODE_TYPE = 9
48
+ # This stores the level to which we have gone finding element inside another element.
49
+ # This is just to make sure that every element has unique name in JSSH.
50
+ @@current_level = 0
51
+ # This stores the name of the element that is about to trigger an Javascript pop up.
52
+ #@@current_js_object = nil
53
+
54
+ attr_accessor :element_name
55
+ #
56
+ # Description:
57
+ # Creates new instance of element. If argument is not nil and is of type string this
58
+ # sets the element_name and element_type property of the object. These properties can
59
+ # be accessed using element_object and element_type methods respectively.
60
+ #
61
+ # Used internally by Firewatir.
62
+ #
63
+ # Input:
64
+ # element - Name of the variable with which the element is referenced in JSSh.
65
+ #
66
+ def initialize(element, container=nil)
67
+ @container = container
68
+ @element_name = element
69
+ @element_type = element_type
70
+ #puts "in initialize "
71
+ #puts caller(0)
72
+ #if(element != nil && element.class == String)
73
+ #@element_name = element
74
+ #elsif(element != nil && element.class == Element)
75
+ # @o = element
76
+ #end
77
+
78
+ #puts "@element_name is #{@element_name}"
79
+ #puts "@element_type is #{@element_type}"
80
+ end
81
+
82
+ private
83
+ def self.def_wrap(ruby_method_name, ole_method_name = nil)
84
+ ole_method_name = ruby_method_name unless ole_method_name
85
+ class_eval "def #{ruby_method_name}
86
+ assert_exists
87
+ # Every element has its name starting from element. If yes then
88
+ # use element_name to send the command to jssh. Else its a number
89
+ # and we are still searching for element, in this case use doc.all
90
+ # array with element_name as index to send command to jssh
91
+ #puts element_object.to_s
92
+ #if(@element_type == 'HTMLDivElement')
93
+ # ole_method_name = 'innerHTML'
94
+ #end
95
+ jssh_socket.send('typeof(' + element_object + '.#{ole_method_name});\n', 0)
96
+ return_type = read_socket()
97
+
98
+ return_value = get_attribute_value(\"#{ole_method_name}\")
99
+
100
+ #if(return_value == '' || return_value == \"null\")
101
+ # return_value = \"\"
102
+ #end
103
+
104
+ if(return_type == \"boolean\")
105
+ return_value = false if return_value == \"false\"
106
+ return_value = true if return_value == \"true\"
107
+ end
108
+ #puts return_value
109
+ @@current_level = 0
110
+ return return_value
111
+ end"
112
+ end
113
+
114
+ def get_attribute_value(attribute_name)
115
+ #if the attribut name is columnLength get number of cells in first row if rows exist.
116
+ if(attribute_name == "columnLength")
117
+ jssh_socket.send("#{element_object}.columns;\n", 0)
118
+ rowsLength = read_socket()
119
+ if(rowsLength != 0 || rowsLength != "")
120
+ jssh_socket.send("#{element_object}.rows[0].cells.length;\n", 0)
121
+ return_value = read_socket()
122
+ return return_value
123
+ end
124
+ end
125
+ if(attribute_name == "text")
126
+ return text()
127
+ end
128
+ if(attribute_name == "url" or attribute_name == "href" or attribute_name == "src" or attribute_name == "action" or attribute_name == "name")
129
+ jssh_socket.send("#{element_object}.getAttribute(\"#{attribute_name}\");\n" , 0)
130
+ return_value = read_socket()
131
+ else
132
+ jssh_command = "var attribute = '';
133
+ if(#{element_object}.#{attribute_name} != undefined)
134
+ attribute = #{element_object}.#{attribute_name};
135
+ else
136
+ attribute = #{element_object}.getAttribute(\"#{attribute_name}\");
137
+ attribute;"
138
+ jssh_command.gsub!("\n", "")
139
+ jssh_socket.send("#{jssh_command};\n", 0)
140
+ #puts jssh_command
141
+ return_value = read_socket()
142
+ end
143
+ if(attribute_name == "value")
144
+ jssh_socket.send("#{element_object}.tagName;\n", 0)
145
+ tagName = read_socket().downcase
146
+ jssh_socket.send("#{element_object}.type;\n", 0)
147
+ type = read_socket().downcase
148
+
149
+ if(tagName == "button" or type == "image" or type == "submit" or type == "reset" or type == "button")
150
+ if(return_value == "" or return_value == "null")
151
+ jssh_socket.send("#{element_object}.innerHTML;\n",0)
152
+ return_value = read_socket()
153
+ end
154
+ end
155
+ end
156
+ #puts "return value of attribute \"{attribute_name}\" is : #{return_value}"
157
+ if(return_value == "null" or return_value == "")
158
+ return_value = ""
159
+ end
160
+
161
+ if(return_value =~ /\[object\s.*\]/)
162
+ return ""
163
+ else
164
+ return return_value
165
+ end
166
+
167
+ end
168
+ private:get_attribute_value
169
+
170
+
171
+ #
172
+ # Description:
173
+ # Returns an array of the properties of an element, in a format to be used by the to_s method.
174
+ # additional attributes are returned based on the supplied atributes hash.
175
+ # name, type, id, value and disabled attributes are common to all the elements.
176
+ # This method is used internally by to_s method.
177
+ #
178
+ # Output:
179
+ # Array with values of the following properties:
180
+ # name, type, id, value disabled and the supplied attribues list.
181
+ #
182
+ def string_creator(attributes = nil)
183
+ n = []
184
+ n << "name:".ljust(TO_S_SIZE) + get_attribute_value("name")
185
+ n << "type:".ljust(TO_S_SIZE) + get_attribute_value("type")
186
+ n << "id:".ljust(TO_S_SIZE) + get_attribute_value("id")
187
+ n << "value:".ljust(TO_S_SIZE) + get_attribute_value("value")
188
+ n << "disabled:".ljust(TO_S_SIZE) + get_attribute_value("disabled")
189
+ #n << "style:".ljust(TO_S_SIZE) + get_attribute_value("style")
190
+ #n << "class:".ljust(TO_S_SIZE) + get_attribute_value("className")
191
+
192
+ if(attributes != nil)
193
+ attributes.each do |key,value|
194
+ n << "#{key}:".ljust(TO_S_SIZE) + get_attribute_value(value)
195
+ end
196
+ end
197
+ return n
198
+ end
199
+
200
+ #
201
+ # Description:
202
+ # Sets and clears the colored highlighting on the currently active element.
203
+ #
204
+ # Input:
205
+ # set_or_clear - this can have following two values
206
+ # :set - To set the color of the element.
207
+ # :clear - To clear the color of the element.
208
+ #
209
+ def highlight(set_or_clear)
210
+ if set_or_clear == :set
211
+ #puts "element_name is : #{element_object}"
212
+ jssh_command = " var original_color = #{element_object}.style.background;"
213
+ jssh_command += " #{element_object}.style.background = \"#{DEFAULT_HIGHLIGHT_COLOR}\"; original_color;"
214
+
215
+ # TODO: Need to change this so that it would work if user sets any other color.
216
+ #puts "color is : #{DEFAULT_HIGHLIGHT_COLOR}"
217
+ jssh_socket.send("#{jssh_command}\n", 0)
218
+ @original_color = read_socket()
219
+
220
+ else # BUG: assumes is :clear, but could actually be anything
221
+ begin
222
+ jssh_socket.send("#{element_object}.style.background = \"#{@original_color}\";\n", 0)
223
+ read_socket()
224
+ rescue
225
+ # we could be here for a number of reasons...
226
+ # e.g. page may have reloaded and the reference is no longer valid
227
+ ensure
228
+ @original_color = nil
229
+ end
230
+ end
231
+ end
232
+ protected :highlight
233
+
234
+ #
235
+ # Description:
236
+ # Returns array of rows for a given table. Returns nil if calling element is not of table type.
237
+ #
238
+ # Output:
239
+ # Array of row elements in an table or nil
240
+ #
241
+ def get_rows()
242
+ #puts "#{element_object} and #{element_type}"
243
+ if(element_type == "HTMLTableElement")
244
+ jssh_socket.send("#{element_object}.rows.length;\n", 0)
245
+ length = read_socket().to_i
246
+ #puts "The number of rows in the table are : #{no_of_rows}"
247
+ return_array = Array.new(length)
248
+ for i in 0..length - 1 do
249
+ return_array[i] = "#{element_object}.rows[#{i}]"
250
+ end
251
+ return return_array
252
+ else
253
+ puts "Trying to access rows for Element of type #{element_type}. Element must be of table type to execute this function."
254
+ return nil
255
+ end
256
+ end
257
+ private :get_rows
258
+
259
+ #
260
+ # Description:
261
+ # Locates the element on the page depending upon the parameters passed. Logic for locating the element is written
262
+ # in JavaScript and then send to JSSh; so that we don't make small round-trips via socket to JSSh. This is done to
263
+ # improve the performance for locating the element.
264
+ #
265
+ # Input:
266
+ # tag - Tag name of the element to be located like "input", "a" etc. This is case insensitive.
267
+ # how - The attribute by which you want to locate the element like id, name etc. You can use any attribute-value pair
268
+ # that uniquely identifies that element on the page. If there are more that one element that have identical
269
+ # attribute-value pair then first element that is found while traversing the DOM will be returned.
270
+ # what - The value of the attribute specified by how.
271
+ # types - Used if that HTML element to be located has different type like input can be of type image, button etc.
272
+ # Default value is nil
273
+ # value - This is used only in case of radio buttons where they have same name but different value.
274
+ #
275
+ # Output:
276
+ # Returns nil if unable to locate the element, else return the element.
277
+ #
278
+ def locate_tagged_element(tag, how, what, types = nil, value = nil)
279
+ #puts caller(0)
280
+ how = :value if how == :caption
281
+ how = :href if how == :url
282
+ #puts "current element is : #{@container.class} and tag is #{tag}"
283
+ # If there is no current element i.e. element in current context we are searching the whole DOM tree.
284
+ # So get all the elements.
285
+
286
+ if(types != nil and types.include?("button"))
287
+ jssh_command = "var isButtonElement = true;"
288
+ else
289
+ jssh_command = "var isButtonElement = false;"
290
+ end
291
+
292
+ # Because in both the below cases we need to get element with respect to document.
293
+ # when we locate a frame document is automatically adjusted to point to HTML inside the frame
294
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
295
+ #end
296
+ #if(@@current_element_object == "")
297
+ jssh_command += "var elements_#{tag} = null; elements_#{tag} = #{DOCUMENT_VAR}.getElementsByTagName(\"#{tag}\");"
298
+ if(types != nil and (types.include?("textarea") or types.include?("button")) )
299
+ jssh_command += "elements_#{tag} = #{DOCUMENT_VAR}.body.getElementsByTagName(\"*\");"
300
+ end
301
+ # @@has_changed = true
302
+ else
303
+ #puts "container name is: " + @container.element_name
304
+ #locate if defined? locate
305
+ #@container.locate
306
+ jssh_command += "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
307
+ if(types != nil and (types.include?("textarea") or types.include?("button") ) )
308
+ jssh_command += "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
309
+ end
310
+ # @@has_changed = false
311
+ end
312
+
313
+
314
+ if(types != nil)
315
+ jssh_command += "var types = new Array("
316
+ count = 0
317
+ types.each do |type|
318
+ if count == 0
319
+ jssh_command += "\"#{type}\""
320
+ count += 1
321
+ else
322
+ jssh_command += ",\"#{type}\""
323
+ end
324
+ end
325
+ jssh_command += ");"
326
+ else
327
+ jssh_command += "var types = null;"
328
+ end
329
+ #jssh_command += "var elements = #{element_object}.getElementsByTagName('*');"
330
+ jssh_command += "var object_index = 1; var o = null; var element_name = '';"
331
+
332
+ if(value == nil)
333
+ jssh_command += "var value = null;"
334
+ else
335
+ jssh_command += "var value = \"#{value}\";"
336
+ end
337
+ #jssh_command += "elements.length;"
338
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
339
+
340
+ jssh_command += "for(var i=0; i<elements_#{tag}.length; i++)
341
+ {
342
+ if(element_name != \"\") break;
343
+ var element = elements_#{tag}[i];"
344
+ else
345
+ jssh_command += "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
346
+ {
347
+ if(element_name != \"\") break;
348
+ var element = elements_#{@@current_level}_#{tag}[i];"
349
+ end
350
+
351
+ # Because in IE for button the value of "value" attribute also corresponds to the innerHTML if value attribute
352
+ # is not supplied. For e.g.: <button>Sign In</button>, in this case value of "value" attribute is "Sign In"
353
+ # though value attribute is not supplied. But for Firefox value of "value" attribute is null. So to make sure
354
+ # script runs on both IE and Watir we are also considering innerHTML if element is of button type.
355
+ jssh_command += " var attribute = '';
356
+ var same_type = false;
357
+ if(types)
358
+ {
359
+ for(var j=0; j<types.length; j++)
360
+ {
361
+ if(types[j] == element.type || types[j] == element.tagName)
362
+ {
363
+ same_type = true;
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ else
369
+ {
370
+ same_type = true;
371
+ }
372
+ if(same_type == true)
373
+ {
374
+ if(\"index\" == \"#{how}\")
375
+ {
376
+ attribute = object_index; object_index += 1;
377
+ }
378
+ else
379
+ {
380
+ if(\"text\" == \"#{how}\")
381
+ {
382
+ attribute = element.textContent;
383
+ }
384
+ else
385
+ {
386
+ if(\"#{how}\" == \"href\" || \"#{how}\" == \"src\" || \"#{how}\" == \"action\" || \"#{how}\" == \"name\")
387
+ {
388
+ attribute = element.getAttribute(\"#{how}\");
389
+ }
390
+ else
391
+ {
392
+ if(element.#{how} != undefined)
393
+ attribute = element.#{how};
394
+ else
395
+ attribute = element.getAttribute(\"#{how}\");
396
+ }
397
+ }
398
+ if(\"value\" == \"#{how}\" && isButtonElement && (attribute == null || attribute == ''))
399
+ {
400
+ attribute = element.innerHTML;
401
+ }
402
+ }
403
+ if(attribute == \"\") o = 'NoMethodError';
404
+ var found = false;"
405
+
406
+ if(what.class == Regexp)
407
+ # Construct the regular expression because we can't use it directly by converting it to string.
408
+ # If reg ex is /Google/i then its string conversion will be (?i-mx:Google) so we can't use it.
409
+ # Construct the regular expression again from the string conversion.
410
+ oldRegExp = what.to_s
411
+ newRegExp = what.inspect
412
+ flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
413
+
414
+ for i in 0..flags.length do
415
+ flag = flags[i, 1]
416
+ if(flag == '-')
417
+ break;
418
+ else
419
+ newRegExp << flag
420
+ end
421
+ end
422
+ #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
423
+ jssh_command += " var regExp = new RegExp(#{newRegExp});
424
+ found = regExp.test(attribute);"
425
+ elsif(how == :index)
426
+ jssh_command += " found = (attribute == #{what});"
427
+ else
428
+ jssh_command += " found = (attribute == \"#{what}\");"
429
+ end
430
+ #jssh_command += " found;"
431
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
432
+ jssh_command += " if(found)
433
+ {
434
+ if(value)
435
+ {
436
+ if(element.value == \"#{value}\")
437
+ {
438
+ o = element;
439
+ element_name = \"elements_#{tag}[\" + i + \"]\";
440
+ break;
441
+ }
442
+ }
443
+ else
444
+ {
445
+ o = element;
446
+ element_name = \"elements_#{tag}[\" + i + \"]\";
447
+ break;
448
+ }
449
+ }"
450
+ else
451
+ jssh_command += " if(found)
452
+ {
453
+ if(value)
454
+ {
455
+ if(element.value == \"#{value}\")
456
+ {
457
+ o = element;
458
+ element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
459
+ break;
460
+ }
461
+ }
462
+ else
463
+ {
464
+ o = element;
465
+ element_name = \"elements_#{@@current_level}_#{tag}[\" + i + \"]\";
466
+ break;
467
+ }
468
+ }"
469
+ end
470
+ jssh_command +=" }
471
+ }
472
+ element_name;"
473
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
474
+ jssh_command.gsub!(/\n/, "")
475
+ #puts jssh_command
476
+ jssh_socket.send("#{jssh_command};\n", 0)
477
+ element_name = read_socket();
478
+ #puts "element name in find control is : #{element_name}"
479
+ @@current_level = @@current_level + 1
480
+ #puts @container
481
+ #puts element_name
482
+ if(element_name != "")
483
+ return element_name #Element.new(element_name, @container)
484
+ else
485
+ return nil
486
+ end
487
+ end
488
+
489
+ #
490
+ # Description:
491
+ # Locates frame element. Logic for locating the frame is written in JavaScript so that we don't make small
492
+ # round trips to JSSh using socket. This is done to improve the performance for locating the element.
493
+ #
494
+ # Input:
495
+ # how - The attribute for locating the frame. You can use any attribute-value pair that uniquely identifies
496
+ # the frame on the page. If there are more than one frames that have identical attribute-value pair
497
+ # then first frame that is found while traversing the DOM will be returned.
498
+ # what - Value of the attribute specified by how
499
+ #
500
+ # Output:
501
+ # Nil if unable to locate frame, else return the Frame element.
502
+ #
503
+ def locate_frame(how, what)
504
+ # Get all the frames the are there on the page.
505
+ #puts "how is #{how} and what is #{what}"
506
+ jssh_command = ""
507
+ if(@container.class == FireWatir::Firefox)
508
+ jssh_command = "var frameset = #{WINDOW_VAR}.frames;
509
+ var elements_frames = new Array();
510
+ for(var i = 0; i < frameset.length; i++)
511
+ {
512
+ var frames = frameset[i].frames;
513
+ for(var j = 0; j < frames.length; j++)
514
+ {
515
+ elements_frames.push(frames[j].frameElement);
516
+ }
517
+ }"
518
+ else
519
+ jssh_command = "var frames = #{@container.element_name}.contentWindow.frames;
520
+ var elements_frames_#{@@current_level} = new Array();
521
+ for(var i = 0; i < frames.length; i++)
522
+ {
523
+ elements_frames_#{@@current_level}.push(frames[i].frameElement);
524
+ }"
525
+ end
526
+
527
+ jssh_command +=" var element_name = ''; var object_index = 1;var attribute = '';
528
+ var element = '';"
529
+ if(@container.class == FireWatir::Firefox)
530
+ jssh_command += "for(var i = 0; i < elements_frames.length; i++)
531
+ {
532
+ element = elements_frames[i];"
533
+ else
534
+ jssh_command += "for(var i = 0; i < elements_frames_#{@@current_level}.length; i++)
535
+ {
536
+ element = elements_frames_#{@@current_level}[i];"
537
+ end
538
+ jssh_command += " if(\"index\" == \"#{how}\")
539
+ {
540
+ attribute = object_index; object_index += 1;
541
+ }
542
+ else
543
+ {
544
+ attribute = element.getAttribute(\"#{how}\");
545
+ if(attribute == \"\" || attribute == null)
546
+ {
547
+ attribute = element.#{how};
548
+ }
549
+ }
550
+ var found = false;"
551
+ if(what.class == Regexp)
552
+ oldRegExp = what.to_s
553
+ newRegExp = "/" + what.source + "/"
554
+ flags = oldRegExp.slice(2, oldRegExp.index(':') - 2)
555
+
556
+ for i in 0..flags.length do
557
+ flag = flags[i, 1]
558
+ if(flag == '-')
559
+ break;
560
+ else
561
+ newRegExp << flag
562
+ end
563
+ end
564
+ #puts "old reg ex is #{what} new reg ex is #{newRegExp}"
565
+ jssh_command += " var regExp = new RegExp(#{newRegExp});
566
+ found = regExp.test(attribute);"
567
+ elsif(how == :index)
568
+ jssh_command += " found = (attribute == #{what});"
569
+ else
570
+ jssh_command += " found = (attribute == \"#{what}\");"
571
+ end
572
+
573
+ jssh_command += " if(found)
574
+ {"
575
+ if(@container.class == FireWatir::Firefox)
576
+ jssh_command += " element_name = \"elements_frames[\" + i + \"]\";
577
+ #{DOCUMENT_VAR} = elements_frames[i].contentDocument;
578
+ #{BODY_VAR} = #{DOCUMENT_VAR}.body;"
579
+ else
580
+ jssh_command += " element_name = \"elements_frames_#{@@current_level}[\" + i + \"]\";
581
+ #{DOCUMENT_VAR} = elements_frames_#{@@current_level}[i].contentDocument;
582
+ #{BODY_VAR} = #{DOCUMENT_VAR}.body;"
583
+ end
584
+ jssh_command += " break;
585
+ }
586
+ }
587
+ element_name;"
588
+
589
+ jssh_command.gsub!("\n", "")
590
+ #puts "jssh_command for finding frame is : #{jssh_command}"
591
+
592
+ jssh_socket.send("#{jssh_command};\n", 0)
593
+ element_name = read_socket()
594
+ @@current_level = @@current_level + 1
595
+ #puts "element_name for frame is : #{element_name}"
596
+
597
+ if(element_name != "")
598
+ return element_name
599
+ else
600
+ return nil
601
+ end
602
+ end
603
+
604
+ def get_frame_html
605
+ jssh_socket.send("var htmlelem = #{DOCUMENT_VAR}.getElementsByTagName('html')[0]; htmlelem.innerHTML;\n", 0)
606
+ #jssh_socket.send("#{BODY_VAR}.innerHTML;\n", 0)
607
+ result = read_socket()
608
+ return "<html>" + result + "</html>"
609
+ end
610
+
611
+ def submit_form
612
+ #puts "form name is : #{element_object}"
613
+ jssh_socket.send("#{element_object}.submit();\n" , 0)
614
+ read_socket()
615
+ end
616
+
617
+ public
618
+
619
+ #
620
+ #
621
+ # Description:
622
+ # Matches the given text with the current text shown in the browser for that particular element.
623
+ #
624
+ # Input:
625
+ # target - Text to match. Can be a string or regex
626
+ #
627
+ # Output:
628
+ # Returns the index if the specified text was found.
629
+ # Returns matchdata object if the specified regexp was found.
630
+ #
631
+ def contains_text(target)
632
+ #puts "Text to match is : #{match_text}"
633
+ #puts "Html is : #{self.text}"
634
+ if target.kind_of? Regexp
635
+ self.text.match(target)
636
+ elsif target.kind_of? String
637
+ self.text.index(target)
638
+ else
639
+ raise ArgumentError, "Argument #{target} should be a string or regexp."
640
+ end
641
+ end
642
+ #
643
+ # Description:
644
+ # Method for inspecting the object. Defined here because IRB was not able to locate the object.
645
+ # TODO: Need to find out why IRB is unable to find object though both (this and IRB) are executing same statements
646
+ #
647
+ def inspect
648
+ assert_exists
649
+ puts self.to_s
650
+ end
651
+
652
+ #
653
+ # Description:
654
+ # Returns array of elements that matches a given XPath query.
655
+ # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
656
+ # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
657
+ # Used internally by Firewatir use ff.elements_by_xpath instead.
658
+ #
659
+ # Input:
660
+ # xpath - The xpath expression or query.
661
+ #
662
+ # Output:
663
+ # Array of elements that matched the xpath expression provided as parameter.
664
+ #
665
+ def elements_by_xpath(container, xpath)
666
+ rand_no = rand(1000)
667
+ #jssh_command = "var xpathResult = #{DOCUMENT_VAR}.evaluate(\"count(#{xpath})\", #{DOCUMENT_VAR}, null, #{NUMBER_TYPE}, null); xpathResult.numberValue;"
668
+ #jssh_socket.send("#{jssh_command}\n", 0);
669
+ #node_count = read_socket()
670
+
671
+ jssh_command = "var element_xpath_#{rand_no} = new Array();"
672
+
673
+ jssh_command += "var result = #{DOCUMENT_VAR}.evaluate(\"#{xpath}\", #{DOCUMENT_VAR}, null, #{ORDERED_NODE_ITERATOR_TYPE}, null);
674
+ var iterate = result.iterateNext();
675
+ while(iterate)
676
+ {
677
+ element_xpath_#{rand_no}.push(iterate);
678
+ iterate = result.iterateNext();
679
+ }
680
+ element_xpath_#{rand_no}.length;
681
+ "
682
+
683
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
684
+ jssh_command.gsub!(/\n/, "")
685
+ #puts jssh_command
686
+ jssh_socket.send("#{jssh_command};\n", 0)
687
+ node_count = read_socket()
688
+ #puts "value of count is : #{node_count}"
689
+
690
+ elements = Array.new(node_count.to_i)
691
+
692
+ for i in 0..elements.length - 1 do
693
+ elements[i] = "element_xpath_#{rand_no}[#{i}]"
694
+ end
695
+
696
+ return elements;
697
+ end
698
+
699
+ #
700
+ # Description:
701
+ # Returns first element found while traversing the DOM; that matches an given XPath query.
702
+ # Mozilla browser directly supports XPath query on its DOM. So no need to create the DOM tree as WATiR does for IE.
703
+ # Refer: http://developer.mozilla.org/en/docs/DOM:document.evaluate
704
+ # Used internally by Firewatir use ff.element_by_xpath instead.
705
+ #
706
+ # Input:
707
+ # xpath - The xpath expression or query.
708
+ #
709
+ # Output:
710
+ # First element in DOM that matched the XPath expression or query.
711
+ #
712
+ def element_by_xpath(container, xpath)
713
+ #puts "here locating element by xpath"
714
+ rand_no = rand(1000)
715
+ jssh_command = "var element_xpath_#{rand_no} = null; element_xpath_#{rand_no} = #{DOCUMENT_VAR}.evaluate(\"#{xpath}\", #{DOCUMENT_VAR}, null, #{FIRST_ORDERED_NODE_TYPE}, null).singleNodeValue; element_xpath_#{rand_no};"
716
+
717
+ jssh_socket.send("#{jssh_command}\n", 0)
718
+ result = read_socket()
719
+ #puts "command send to jssh is : #{jssh_command}"
720
+ #puts "result is : #{result}"
721
+ if(result == "null" || result == "" || result.include?("exception"))
722
+ @@current_level = 0
723
+ return nil
724
+ else
725
+ @@current_level += 1
726
+ return "element_xpath_#{rand_no}"
727
+ end
728
+ end
729
+
730
+ #
731
+ # Description:
732
+ # Returns the name of the element with which we can access it in JSSh.
733
+ # Used internally by Firewatir to execute methods, set properties or return property value for the element.
734
+ #
735
+ # Output:
736
+ # Name of the variable with which element is referenced in JSSh
737
+ #
738
+ def element_object
739
+ #puts caller.join("\n")
740
+ #puts "In element_object element name is : #{@element_name}"
741
+ #puts "in element_object : #{@container.class}"
742
+ #if(@container.class == FireWatir::Firefox)
743
+ return @element_name #if @element_name != nil
744
+ #else
745
+ # return @container.element_name
746
+ #end
747
+ #return @o.element_name if @o != nil
748
+ end
749
+ private :element_object
750
+
751
+ #
752
+ # Description:
753
+ # Returns the type of element. For e.g.: HTMLAnchorElement. used internally by Firewatir
754
+ #
755
+ # Output:
756
+ # Type of the element.
757
+ #
758
+ def element_type
759
+ #puts "in element_type object is : #{element_object}"
760
+ # Get the type of the element.
761
+ jssh_socket.send("#{element_object};\n", 0)
762
+ temp = read_socket()
763
+
764
+ if temp == ""
765
+ return nil
766
+ end
767
+
768
+ #puts "#{element_object} and type is #{temp}"
769
+ temp =~ /\[object\s(.*)\]/
770
+ if $1
771
+ return $1
772
+ else
773
+ # This is done because in JSSh if you write element name of anchor type
774
+ # then it displays the link to which it navigates instead of displaying
775
+ # object type. So above regex match will return nil
776
+ return "HTMLAnchorElement"
777
+ end
778
+ end
779
+ #private :element_type
780
+
781
+ #
782
+ # Description:
783
+ # Fires the provided event for an element and by default waits for the action to get completed.
784
+ #
785
+ # Input:
786
+ # event - Event to be fired like "onclick", "onchange" etc.
787
+ # wait - Whether to wait for the action to get completed or not. By default its true.
788
+ #
789
+ # TODO: Provide ability to specify event parameters like keycode for key events, and click screen
790
+ # coordinates for mouse events.
791
+ def fire_event(event, wait = true)
792
+ assert_exists()
793
+ event = event.to_s # in case event was given as a symbol
794
+
795
+ event = event.downcase
796
+
797
+ event =~ /on(.*)/i
798
+ event = $1 if $1
799
+
800
+ # check if we've got an old-school on-event
801
+ #jssh_socket.send("typeof(#{element_object}.#{event});\n", 0)
802
+ #is_defined = read_socket()
803
+
804
+ # info about event types harvested from:
805
+ # http://www.howtocreate.co.uk/tutorials/javascript/domevents
806
+ case event
807
+ when 'abort', 'blur', 'change', 'error', 'focus', 'load', 'reset', 'resize',
808
+ 'scroll', 'select', 'submit', 'unload'
809
+ dom_event_type = 'HTMLEvents'
810
+ dom_event_init = "initEvent(\"#{event}\", true, true)"
811
+ when 'keydown', 'keypress', 'keyup'
812
+ dom_event_type = 'KeyEvents'
813
+ # Firefox has a proprietary initializer for keydown/keypress/keyup.
814
+ # Args are as follows:
815
+ # 'type', bubbles, cancelable, windowObject, ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
816
+ dom_event_init = "initKeyEvent(\"#{event}\", true, true, #{WINDOW_VAR}, false, false, false, false, 0, 0)"
817
+ when 'click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover',
818
+ 'mouseup'
819
+ dom_event_type = 'MouseEvents'
820
+ # Args are as follows:
821
+ # 'type', bubbles, cancelable, windowObject, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget
822
+ dom_event_init = "initMouseEvent(\"#{event}\", true, true, #{WINDOW_VAR}, 1, 0, 0, 0, 0, false, false, false, false, 0, null)"
823
+ else
824
+ dom_event_type = 'HTMLEvents'
825
+ dom_event_init = "initEvents(\"#{event}\", true, true)"
826
+ end
827
+
828
+ if(element_type == "HTMLSelectElement")
829
+ dom_event_type = 'HTMLEvents'
830
+ dom_event_init = "initEvent(\"#{event}\", true, true)"
831
+ end
832
+
833
+
834
+ jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"#{dom_event_type}\"); "
835
+ jssh_command << "event.#{dom_event_init}; "
836
+ jssh_command << "#{element_object}.dispatchEvent(event);"
837
+
838
+ #puts "JSSH COMMAND:\n#{jssh_command}\n"
839
+
840
+ jssh_socket.send("#{jssh_command}\n", 0)
841
+ read_socket() if wait
842
+ wait() if wait
843
+
844
+ @@current_level = 0
845
+ end
846
+ alias fireEvent fire_event
847
+
848
+ #
849
+ # Description:
850
+ # Returns the value of the specified attribute of an element.
851
+ #
852
+ def attribute_value(attribute_name)
853
+ #puts attribute_name
854
+ assert_exists()
855
+ return_value = get_attribute_value(attribute_name)
856
+ @@current_level = 0
857
+ return return_value
858
+ end
859
+
860
+ #
861
+ # Description:
862
+ # Checks if element exists or not. Raises UnknownObjectException if element doesn't exists.
863
+ #
864
+ def assert_exists
865
+ unless exists?
866
+ raise UnknownObjectException.new("Unable to locate object, using #{@how} and #{@what}")
867
+ end
868
+ end
869
+
870
+ #
871
+ # Description:
872
+ # Checks if element is enabled or not. Raises ObjectDisabledException if object is disabled and
873
+ # you are trying to use the object.
874
+ #
875
+ def assert_enabled
876
+ unless enabled?
877
+ raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
878
+ end
879
+ end
880
+
881
+ #
882
+ # Description:
883
+ # First checks if element exists or not. Then checks if element is enabled or not.
884
+ #
885
+ # Output:
886
+ # Returns true if element exists and is enabled, else returns false.
887
+ #
888
+ def enabled?
889
+ assert_exists
890
+ jssh_socket.send("#{element_object}.disabled;\n", 0)
891
+ value = read_socket()
892
+ @@current_level = 0
893
+ return true if(value == "false")
894
+ return false if(value == "true")
895
+ return value
896
+ end
897
+
898
+ #
899
+ # Description:
900
+ # Checks if element exists or not. If element is not located yet then first locates the element.
901
+ #
902
+ # Output:
903
+ # True if element exists, false otherwise.
904
+ #
905
+ def exists?
906
+ #puts "element is : #{element_object}"
907
+ # If elements array has changed locate the element again. So that the element name points to correct element.
908
+ if(element_object == nil || element_object == "")
909
+ #puts "locating element"
910
+ locate if defined?(locate)
911
+ if(@element_name == nil || @element_name == "")
912
+ return false
913
+ else
914
+ #puts caller(0)
915
+ #puts "element name is : #{@element_name}"
916
+ return true
917
+ end
918
+ else
919
+ #puts "not locating the element again"
920
+ return true
921
+ end
922
+ @@current_level = 0
923
+ if(element_object == nil || element_object == "")
924
+ return false
925
+ else
926
+ return true
927
+ end
928
+ end
929
+
930
+ #
931
+ # Description:
932
+ # Returns the text of the element.
933
+ #
934
+ # Output:
935
+ # Text of the element.
936
+ #
937
+ def text()
938
+ assert_exists
939
+
940
+ if(element_type == "HTMLFrameElement")
941
+ jssh_socket.send("#{BODY_VAR}.textContent;\n", 0)
942
+ else
943
+ jssh_socket.send("#{element_object}.textContent;\n", 0)
944
+ end
945
+
946
+ return_value = read_socket().strip()
947
+ #puts "text content of element is : #{return_value}"
948
+
949
+ #if(returnType == "boolean")
950
+ # return_value = false if returnValue == "false"
951
+ # return_value = true if returnValue == "true"
952
+ #end
953
+ @@current_level = 0
954
+ return return_value
955
+ end
956
+ alias innerText text
957
+
958
+ # Returns the name of the element (as defined in html)
959
+ def_wrap :name
960
+ # Returns the id of the element
961
+ def_wrap :id
962
+ # Returns whether the element is disabled
963
+ def_wrap :disabled
964
+ alias disabled? disabled
965
+ # Returns the state of the element
966
+ def_wrap :checked
967
+ # Returns the value of the element
968
+ def_wrap :value
969
+ # Returns the title of the element
970
+ def_wrap :title
971
+ # Returns the value of 'alt' attribute in case of Image element.
972
+ def_wrap :alt
973
+ # Returns the value of 'href' attribute in case of Anchor element.
974
+ def_wrap :src
975
+ # Returns the type of the element. Use in case of Input element only.
976
+ def_wrap :type
977
+ # Returns the url the Anchor element points to.
978
+ def_wrap :href
979
+ # Return the ID of the control that this label is associated with
980
+ def_wrap :for, :htmlFor
981
+ # Returns the class name of the element
982
+ def_wrap :class_name, :className
983
+ # Return the html of the object
984
+ def_wrap :html, :innerHTML
985
+ # Return the action of form
986
+ def_wrap :action
987
+
988
+ #
989
+ # Description:
990
+ # Display basic details about the object. Sample output for a button is shown.
991
+ # Raises UnknownObjectException if the object is not found.
992
+ # name b4
993
+ # type button
994
+ # id b5
995
+ # value Disabled Button
996
+ # disabled true
997
+ #
998
+ # Output:
999
+ # Array with value of properties shown above.
1000
+ #
1001
+ def to_s(attributes=nil)
1002
+ #puts "here in to_s"
1003
+ #puts caller(0)
1004
+ assert_exists
1005
+ if(element_type == "HTMLTableCellElement")
1006
+ return text()
1007
+ else
1008
+ result = string_creator(attributes) #.join("\n")
1009
+ @@current_level = 0
1010
+ return result
1011
+ end
1012
+ end
1013
+
1014
+ #
1015
+ # Description:
1016
+ # Function to fire click event on elements.
1017
+ #
1018
+ def click
1019
+ assert_exists
1020
+ assert_enabled
1021
+
1022
+ highlight(:set)
1023
+ #puts "#{element_object} and #{element_type}"
1024
+ case element_type
1025
+
1026
+ when "HTMLAnchorElement", "HTMLImageElement"
1027
+ # Special check for link or anchor tag. Because click() doesn't work on links.
1028
+ # More info: http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-48250443
1029
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=148585
1030
+
1031
+ jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"MouseEvents\");"
1032
+
1033
+ # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1034
+ jssh_command += "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1035
+ jssh_command += "#{element_object}.dispatchEvent(event);\n"
1036
+
1037
+ #puts "jssh_command is: #{jssh_command}"
1038
+ jssh_socket.send("#{jssh_command}", 0)
1039
+ read_socket()
1040
+ else
1041
+ jssh_socket.send("typeof(#{element_object}.click);\n", 0)
1042
+ isDefined = read_socket()
1043
+ if(isDefined == "undefined")
1044
+ fire_event("onclick")
1045
+ else
1046
+ jssh_socket.send("#{element_object}.click();\n" , 0)
1047
+ read_socket()
1048
+ end
1049
+ end
1050
+ highlight(:clear)
1051
+ # Wait for firefox to reload.
1052
+ wait()
1053
+ end
1054
+
1055
+ #
1056
+ # Description:
1057
+ # Wait for the browser to get loaded, after the event is being fired.
1058
+ #
1059
+ def wait
1060
+ #ff = FireWatir::Firefox.new
1061
+ #ff.wait()
1062
+ #puts @container
1063
+ @container.wait()
1064
+ @@current_level = 0
1065
+ end
1066
+
1067
+ #
1068
+ # Description:
1069
+ # Function is used for click events that generates javascript pop up.
1070
+ # Doesn't fire the click event immediately instead, it stores the state of the object. User then tells which button
1071
+ # is to be clicked in case a javascript pop up comes after clicking the element. Depending upon the button to be clicked
1072
+ # the functions 'alert' and 'confirm' are re-defined in JavaScript to return appropriate values either true or false. Then the
1073
+ # re-defined functions are send to jssh which then fires the click event of the element using the state
1074
+ # stored above. So the click event is fired in the second statement. Therefore, if you are using this function you
1075
+ # need to call 'click_js_popup_button()' function in the next statement to actually trigger the click event.
1076
+ #
1077
+ # Typical Usage:
1078
+ # ff.button(:id, "button").click_no_wait()
1079
+ # ff.click_js_popup_button("OK")
1080
+ #
1081
+ #def click_no_wait
1082
+ # assert_exists
1083
+ # assert_enabled
1084
+ #
1085
+ # highlight(:set)
1086
+ # @@current_js_object = Element.new("#{element_object}", @container)
1087
+ #end
1088
+
1089
+ #
1090
+ # Description:
1091
+ # Function to click specified button on the javascript pop up. Currently you can only click
1092
+ # either OK or Cancel button.
1093
+ # Functions alert and confirm are redefined so that it doesn't causes the JSSH to get blocked. Also this
1094
+ # will make Firewatir cross platform.
1095
+ #
1096
+ # Input:
1097
+ # button to be clicked
1098
+ #
1099
+ #def click_js_popup(button = "OK")
1100
+ # jssh_command = "var win = #{BROWSER_VAR}.contentWindow;"
1101
+ # if(button =~ /ok/i)
1102
+ # jssh_command += "var popuptext = '';win.alert = function(param) {popuptext = param; return true; };
1103
+ # win.confirm = function(param) {popuptext = param; return true; };"
1104
+ # elsif(button =~ /cancel/i)
1105
+ # jssh_command += "var popuptext = '';win.alert = function(param) {popuptext = param; return false; };
1106
+ # win.confirm = function(param) {popuptext = param; return false; };"
1107
+ # end
1108
+ # jssh_command.gsub!(/\n/, "")
1109
+ # jssh_socket.send("#{jssh_command}\n", 0)
1110
+ # read_socket()
1111
+ # click_js_popup_creator_button()
1112
+ # #jssh_socket.send("popuptext_alert;\n", 0)
1113
+ # #read_socket()
1114
+ # jssh_socket.send("\n", 0)
1115
+ # read_socket()
1116
+ #end
1117
+
1118
+ #
1119
+ # Description:
1120
+ # Clicks on button or link or any element that triggers a javascript pop up.
1121
+ # Used internally by function click_js_popup.
1122
+ #
1123
+ #def click_js_popup_creator_button
1124
+ # #puts @@current_js_object.element_name
1125
+ # jssh_socket.send("#{@@current_js_object.element_name}\n;", 0)
1126
+ # temp = read_socket()
1127
+ # temp =~ /\[object\s(.*)\]/
1128
+ # if $1
1129
+ # type = $1
1130
+ # else
1131
+ # # This is done because in JSSh if you write element name of anchor type
1132
+ # # then it displays the link to which it navigates instead of displaying
1133
+ # # object type. So above regex match will return nil
1134
+ # type = "HTMLAnchorElement"
1135
+ # end
1136
+ # #puts type
1137
+ # case type
1138
+ # when "HTMLAnchorElement", "HTMLImageElement"
1139
+ # jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"MouseEvents\");"
1140
+ # # Info about initMouseEvent at: http://www.xulplanet.com/references/objref/MouseEvent.html
1141
+ # jssh_command += "event.initMouseEvent('click',true,true,null,1,0,0,0,0,false,false,false,false,0,null);"
1142
+ # jssh_command += "#{@@current_js_object.element_name}.dispatchEvent(event);\n"
1143
+ #
1144
+ # jssh_socket.send("#{jssh_command}", 0)
1145
+ # read_socket()
1146
+ # when "HTMLDivElement", "HTMLSpanElement"
1147
+ # jssh_socket.send("typeof(#{element_object}.#{event.downcase});\n", 0)
1148
+ # isDefined = read_socket()
1149
+ # #puts "is method there : #{isDefined}"
1150
+ # if(isDefined != "undefined")
1151
+ # if(element_type == "HTMLSelectElement")
1152
+ # jssh_command = "var event = #{DOCUMENT_VAR}.createEvent(\"HTMLEvents\");
1153
+ # event.initEvent(\"click\", true, true);
1154
+ # #{element_object}.dispatchEvent(event);"
1155
+ # jssh_command.gsub!(/\n/, "")
1156
+ # jssh_socket.send("#{jssh_command}\n", 0)
1157
+ # read_socket()
1158
+ # else
1159
+ # jssh_socket.send("#{element_object}.#{event.downcase}();\n", 0)
1160
+ # read_socket()
1161
+ # end
1162
+ # end
1163
+ # else
1164
+ # jssh_command = "#{@@current_js_object.element_name}.click();\n";
1165
+ # jssh_socket.send("#{jssh_command}", 0)
1166
+ # read_socket()
1167
+ # end
1168
+ # @@current_level = 0
1169
+ # @@current_js_object = nil
1170
+ #end
1171
+ #private :click_js_popup_creator_button
1172
+
1173
+ #
1174
+ # Description:
1175
+ # Gets all the options of the select list element.
1176
+ #
1177
+ # Output:
1178
+ # Array of option elements.
1179
+ #
1180
+ def options
1181
+ jssh_socket.send("#{element_object}.options.length;\n", 0)
1182
+ length = read_socket().to_i
1183
+ #puts "options length is : #{length}"
1184
+ arr_options = Array.new(length)
1185
+ for i in 0..length - 1
1186
+ arr_options[i] = "#{element_object}.options[#{i}]"
1187
+ end
1188
+ return arr_options
1189
+ end
1190
+ private :options
1191
+
1192
+ #
1193
+ # Description:
1194
+ # Used to get class name for option element. Used internally by Firewatir use ff.select_list(...).option(..).class
1195
+ #
1196
+ # Output:
1197
+ # Class name of option element.
1198
+ #
1199
+ def option_class_name
1200
+ jssh_socket.send("#{element_object}.className;\n", 0)
1201
+ return read_socket()
1202
+ end
1203
+ private :option_class_name
1204
+
1205
+ #
1206
+ # Description:
1207
+ # Used to get text for option element. Used internally by Firewatir use ff.select_list(...).option(..).text
1208
+ #
1209
+ # Output:
1210
+ # Text of option element.
1211
+ #
1212
+ def option_text
1213
+ jssh_socket.send("#{element_object}.text;\n", 0)
1214
+ return read_socket()
1215
+ end
1216
+ private :option_text
1217
+
1218
+ #
1219
+ # Description:
1220
+ # Used to get value for option element. Used internally by Firewatir use ff.select_list(...).option(..).value
1221
+ #
1222
+ # Output:
1223
+ # Value of option element.
1224
+ #
1225
+ def option_value
1226
+ jssh_socket.send("#{element_object}.value;\n", 0)
1227
+ return read_socket()
1228
+ end
1229
+ private :option_value
1230
+
1231
+ #
1232
+ # Description:
1233
+ # Used to check if option is selected or not. Used internally by Firewatir use ff.select_list(...).option(..).selected
1234
+ #
1235
+ # Output:
1236
+ # True if option is selected, false otherwise.
1237
+ #
1238
+ def option_selected
1239
+ jssh_socket.send("#{element_object}.selected;\n", 0)
1240
+ value = read_socket()
1241
+ return true if value == "true"
1242
+ return false if value == "false"
1243
+ end
1244
+ private :option_selected
1245
+
1246
+ #
1247
+ # Description:
1248
+ # Gets all the cells of the row of a table.
1249
+ #
1250
+ # Output:
1251
+ # Array of table cell elements.
1252
+ #
1253
+ def get_cells
1254
+ assert_exists
1255
+ #puts "element name in cells is : #{element_object}"
1256
+ if(element_type == "HTMLTableRowElement")
1257
+ jssh_socket.send("#{element_object}.cells.length;\n", 0)
1258
+ length = read_socket.to_i
1259
+ return_array = Array.new(length)
1260
+ for i in 0..length - 1 do
1261
+ return_array[i] = "#{element_object}.cells[#{i}]"
1262
+ end
1263
+ return return_array
1264
+ else
1265
+ puts "The element must be of table row type to execute this function."
1266
+ return nil
1267
+ end
1268
+ end
1269
+ private :get_cells
1270
+
1271
+ #
1272
+ # Description:
1273
+ # Sets the value of file in HTMLInput file field control.
1274
+ #
1275
+ # Input:
1276
+ # setPath - location of the file to be uploaded. '|' should not be part of filename.
1277
+ #
1278
+ def setFileFieldValue(setPath)
1279
+ # As ruby converts \\ to \ and while sending name to jssh \ is ignored.
1280
+ # So replace \ with \\. Now this is even trickier you can't replace \ with \\
1281
+ # directly like this string.gsub!("\\", "\\\\") this doesn't work.
1282
+ # Work around is replace '\' with two special character and then replace
1283
+ # special character with \.
1284
+ setPath.gsub!("\\", "||")
1285
+ setPath.gsub!("|", "\\")
1286
+
1287
+ #jssh_command = "var textBox = #{DOCUMENT_VAR}.getBoxObjectFor(#{element_object}).firstChild;"
1288
+ #jssh_command += "textBox.value = \"#{setPath}\";\n";
1289
+
1290
+ #puts jssh_command
1291
+ jssh_socket.send("#{element_object}.value = \"#{setPath}\";\n", 0)
1292
+ read_socket()
1293
+ @@current_level = 0
1294
+ end
1295
+ private :setFileFieldValue
1296
+
1297
+ #
1298
+ # Description:
1299
+ # Traps all the function calls for an element that is not defined and fires them again
1300
+ # as it is to the jssh. This can be used in case the element supports properties or methods
1301
+ # that are not defined in the corresponding element class or in the base class(Element).
1302
+ #
1303
+ # Input:
1304
+ # methodId - Id of the method that is called.
1305
+ # *args - arguments sent to the methods.
1306
+ #
1307
+ def method_missing(methId, *args)
1308
+ methodName = methId.id2name
1309
+ #puts "method name is : #{methodName}"
1310
+ assert_exists
1311
+ #assert_enabled
1312
+ methodName = "colSpan" if methodName == "colspan"
1313
+ if(methodName =~ /invoke/)
1314
+ jssh_command = "#{element_object}."
1315
+ for i in args do
1316
+ jssh_command += i;
1317
+ end
1318
+ #puts "#{jssh_command}"
1319
+ jssh_socket.send("#{jssh_command};\n", 0)
1320
+ return_value = read_socket()
1321
+ #puts "return value is : #{return_value}"
1322
+ return return_value
1323
+ else
1324
+ #assert_exists
1325
+ #puts "element name is #{element_object}"
1326
+
1327
+ # We get method name with trailing '=' when we try to assign a value to a
1328
+ # property. So just remove the '=' to get the type
1329
+ temp = ""
1330
+ assigning_value = false
1331
+ if(methodName =~ /(.*)=$/)
1332
+ temp = "#{element_object}.#{$1}"
1333
+ assigning_value = true
1334
+ else
1335
+ temp = "#{element_object}.#{methodName}"
1336
+ end
1337
+ #puts "temp is : #{temp}"
1338
+
1339
+ jssh_socket.send("typeof(#{temp});\n", 0)
1340
+ method_type = read_socket()
1341
+ #puts "method_type is : #{method_type}"
1342
+
1343
+ if(assigning_value)
1344
+ if(method_type != "boolean" && args[0].class != Fixnum)
1345
+ args[0].gsub!("\\", "\\"*4)
1346
+ args[0].gsub!("\"", "\\\"")
1347
+ args[0].gsub!("\n","\\n")
1348
+ jssh_command = "#{element_object}.#{methodName}\"#{args[0]}\""
1349
+ else
1350
+ jssh_command = "#{element_object}.#{methodName}#{args[0]}"
1351
+ end
1352
+ #puts "jssh_command is : #{jssh_command}"
1353
+ jssh_socket.send("#{jssh_command};\n", 0)
1354
+ read_socket()
1355
+ return
1356
+ end
1357
+
1358
+ methodName = "#{element_object}.#{methodName}"
1359
+ if(args.length == 0)
1360
+ #puts "In if loop #{methodName}"
1361
+ if(method_type == "function")
1362
+ jssh_command = "#{methodName}();\n"
1363
+ else
1364
+ jssh_command = "#{methodName};\n"
1365
+ end
1366
+ else
1367
+ #puts "In else loop : #{methodName}"
1368
+ jssh_command = "#{methodName}("
1369
+
1370
+ count = 0
1371
+ if args != nil
1372
+ for i in args
1373
+ jssh_command += "," if count != 0
1374
+ if i.kind_of? Numeric
1375
+ jssh_command += i.to_s
1376
+ else
1377
+ jssh_command += "\"#{i.to_s.gsub(/"/,"\\\"")}\""
1378
+ end
1379
+ count = count + 1
1380
+ end
1381
+ end
1382
+
1383
+ jssh_command += ");\n"
1384
+ end
1385
+
1386
+ if(method_type == "boolean")
1387
+ jssh_command = jssh_command.gsub("\"false\"", "false")
1388
+ jssh_command = jssh_command.gsub("\"true\"", "true")
1389
+ end
1390
+ #puts "jssh_command is #{jssh_command}"
1391
+ jssh_socket.send("#{jssh_command}", 0)
1392
+ returnValue = read_socket()
1393
+ #puts "return value is : #{returnValue}"
1394
+
1395
+ @@current_level = 0
1396
+
1397
+ if(method_type == "boolean")
1398
+ return false if(returnValue == "false")
1399
+ return true if(returnValue == "true")
1400
+ elsif(method_type == "number")
1401
+ return returnValue.to_i
1402
+ else
1403
+ return returnValue
1404
+ end
1405
+ end
1406
+ end
1407
+ end
1408
+
1409
+ #
1410
+ # Description:
1411
+ # Class for returning the document element.
1412
+ #
1413
+ class Document
1414
+ include Container
1415
+ @@current_level = 0
1416
+
1417
+ #
1418
+ # Description:
1419
+ # Creates new instance of Document class.
1420
+ #
1421
+ def initialize(container)
1422
+ @length = 0
1423
+ @elements = nil
1424
+ @arr_elements = ""
1425
+ @container = container
1426
+ end
1427
+
1428
+ #
1429
+ # Description:
1430
+ # Find all the elements in the document by querying DOM.
1431
+ # Set the class variables like length and the variable name of array storing the elements in JSSH.
1432
+ #
1433
+ # Output:
1434
+ # Array of elements.
1435
+ #
1436
+ def all
1437
+ @arr_elements = "arr_coll_#{@@current_level}"
1438
+ jssh_command = "var arr_coll_#{@@current_level}=new Array(); "
1439
+
1440
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
1441
+ jssh_command +="var element_collection = null; element_collection = #{DOCUMENT_VAR}.getElementsByTagName(\"*\");
1442
+ if(element_collection != null && typeof(element_collection) != 'undefined')
1443
+ {
1444
+ for (var i = 0; i < element_collection.length; i++)
1445
+ {
1446
+ if((element_collection[i].tagName != 'BR') && (element_collection[i].tagName != 'HR') && (element_collection[i].tagName != 'DOCTYPE') && (element_collection[i].tagName != 'META') && (typeof(element_collection[i].tagName) != 'undefined'))
1447
+ arr_coll_#{@@current_level}.push(element_collection[i]);
1448
+ }
1449
+ }
1450
+ arr_coll_#{@@current_level}.length;"
1451
+ else
1452
+ jssh_command +="var element_collection = null; element_collection = #{@container.element_name}.getElementsByTagName(\"*\");
1453
+ if(element_collection!= null && typeof(element_collection) != 'undefined')
1454
+ {
1455
+ for (var i = 0; i < element_collection.length; i++)
1456
+ {
1457
+ if((element_collection[i].tagName != 'BR') && (element_collection[i].tagName != 'HR') && (element_collection[i].tagName != 'DOCTYPE') && (element_collection[i].tagName != 'META') && (typeof(element_collection[i].tagName) != 'undefined'))
1458
+ arr_coll_#{@@current_level}.push(element_collection[i]);
1459
+ }
1460
+ }
1461
+ arr_coll_#{@@current_level}.length;"
1462
+ end
1463
+
1464
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
1465
+ jssh_command.gsub!(/\n/, "")
1466
+ #puts jssh_command
1467
+ jssh_socket.send("#{jssh_command};\n", 0)
1468
+ @length = read_socket().to_i;
1469
+ #puts "elements length is in locate_tagged_elements is : #{@length}"
1470
+
1471
+ elements = nil
1472
+ elements = Array.new(@length)
1473
+ for i in 0..@length - 1 do
1474
+ temp = Element.new("arr_coll_#{@@current_level}[#{i}]", @container)
1475
+ elements[i] = temp
1476
+ end
1477
+ @@current_level += 1
1478
+ return elements
1479
+
1480
+ end
1481
+
1482
+ #
1483
+ # Description:
1484
+ # Returns the count of elements in the document.
1485
+ #
1486
+ # Output:
1487
+ # Count of elements found in the document.
1488
+ #
1489
+ def length
1490
+ return @length
1491
+ end
1492
+
1493
+ #
1494
+ # Description:
1495
+ # Iterates over elements in the document.
1496
+ #
1497
+ def each
1498
+ for i in 0..@length - 1
1499
+ yield Element.new("#{@arr_elements}[#{i}]", @container)
1500
+ end
1501
+ end
1502
+
1503
+ #
1504
+ # Description:
1505
+ # Gets the element at the nth index in the array of the elements.
1506
+ #
1507
+ # Input:
1508
+ # n - Index of element you want to access. Index is 1 based.
1509
+ #
1510
+ # Output:
1511
+ # Element at the nth index.
1512
+ #
1513
+ def [](n)
1514
+ return Element.new("#{@arr_elements}[#{n-1}]", @container)
1515
+ end
1516
+
1517
+ #
1518
+ # Description:
1519
+ # Get all forms available on the page.
1520
+ # Used internally by Firewatir use ff.show_forms instead.
1521
+ #
1522
+ # Output:
1523
+ # Array containing Form elements
1524
+ #
1525
+ def get_forms()
1526
+ jssh_socket.send("var element_forms = #{DOCUMENT_VAR}.forms; element_forms.length;\n", 0)
1527
+ length = read_socket().to_i
1528
+ forms = Array.new(length)
1529
+
1530
+ for i in 0..length - 1 do
1531
+ forms[i] = Form.new(@container, :jssh_name, "element_forms[#{i}]")
1532
+ end
1533
+ return forms
1534
+ end
1535
+
1536
+ #
1537
+ # Description:
1538
+ # Get all images available on the page.
1539
+ # Used internally by Firewatir use ff.show_images instead.
1540
+ #
1541
+ # Output:
1542
+ # Array containing Image elements
1543
+ #
1544
+ def get_images
1545
+ return Images.new(@container)
1546
+ end
1547
+
1548
+ #
1549
+ # Description:
1550
+ # Get all links available on the page.
1551
+ # Used internally by Firewatir use ff.show_links instead.
1552
+ #
1553
+ # Output:
1554
+ # Array containing Link elements
1555
+ #
1556
+ def get_links
1557
+ return Links.new(@container)
1558
+ end
1559
+
1560
+ #
1561
+ # Description:
1562
+ # Get all divs available on the page.
1563
+ # Used internally by Firewatir use ff.show_divs instead.
1564
+ #
1565
+ # Output:
1566
+ # Array containing Div elements
1567
+ #
1568
+ def get_divs
1569
+ return Divs.new(@container)
1570
+ end
1571
+
1572
+ #
1573
+ # Description:
1574
+ # Get all tables available on the page.
1575
+ # Used internally by Firewatir use ff.show_tables instead.
1576
+ #
1577
+ # Output:
1578
+ # Array containing Table elements
1579
+ #
1580
+ def get_tables
1581
+ return Tables.new(@container)
1582
+ end
1583
+
1584
+ #
1585
+ # Description:
1586
+ # Get all pres available on the page.
1587
+ # Used internally by Firewatir use ff.show_pres instead.
1588
+ #
1589
+ # Output:
1590
+ # Array containing Pre elements
1591
+ #
1592
+ def get_pres
1593
+ return Pres.new(@container)
1594
+ end
1595
+
1596
+ #
1597
+ # Description:
1598
+ # Get all spans available on the page.
1599
+ # Used internally by Firewatir use ff.show_spans instead.
1600
+ #
1601
+ # Output:
1602
+ # Array containing Span elements
1603
+ #
1604
+ def get_spans
1605
+ return Spans.new(@container)
1606
+ end
1607
+
1608
+ #
1609
+ # Description:
1610
+ # Get all labels available on the page.
1611
+ # Used internally by Firewatir use ff.show_labels instead.
1612
+ #
1613
+ # Output:
1614
+ # Array containing Label elements
1615
+ #
1616
+ def get_labels
1617
+ return Labels.new(@container)
1618
+ end
1619
+ end
1620
+
1621
+ #
1622
+ # Description:
1623
+ # Class for iterating over elements of common type like links, images, divs etc.
1624
+ #
1625
+ class ElementCollections
1626
+ include Container
1627
+ @@current_level = 0
1628
+ #
1629
+ # Description:
1630
+ # Initializes new instance of this class.
1631
+ #
1632
+ # Input:
1633
+ # tag - tag name of the element for which you want the iterator.
1634
+ # types - element type. used in case where same element tag has different types like input has type image, button etc.
1635
+ #
1636
+ #def initialize(container, tag , types=nil)
1637
+ # @@current_level += 1
1638
+ # @@current_element_object = Element.get_current_element
1639
+ # #puts " the current object #{@@current_element_object}"
1640
+ # @length = 0
1641
+ # @arr_name = ""
1642
+ # @container = container
1643
+ # @elements = locate_tagged_elements(tag , types)
1644
+ #end
1645
+
1646
+ #
1647
+ # Description:
1648
+ # Locate all the elements of give tag and type.
1649
+ #
1650
+ # Input:
1651
+ # tag - tag name of the element for which you want the iterator.
1652
+ # types - element type. used in case where same element tag has different types like input has type image, button etc.
1653
+ #
1654
+ # Output:
1655
+ # Elements array containing all the elements found on the page.
1656
+ #
1657
+ def locate_tagged_elements(tag , types = nil)
1658
+ jssh_command = "var arr_coll_#{tag}_#{@@current_level}=new Array();"
1659
+ @arr_name = "arr_coll_#{tag}_#{@@current_level}"
1660
+
1661
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
1662
+ jssh_command += "var elements_#{tag} = null; elements_#{tag} = #{DOCUMENT_VAR}.getElementsByTagName(\"#{tag}\");"
1663
+ if(types != nil and (types.include?("textarea") or types.include?("button")) )
1664
+ jssh_command += "elements_#{tag} = #{DOCUMENT_VAR}.body.getElementsByTagName(\"*\");"
1665
+ end
1666
+ else
1667
+ jssh_command += "var elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"#{tag}\");"
1668
+ if(types != nil and (types.include?("textarea") or types.include?("button")) )
1669
+ jssh_command += "elements_#{@@current_level}_#{tag} = #{@container.element_name}.getElementsByTagName(\"*\");"
1670
+ end
1671
+ end
1672
+
1673
+ if(types != nil)
1674
+ jssh_command += "var types = new Array("
1675
+ count = 0
1676
+ types.each do |type|
1677
+ if count == 0
1678
+ jssh_command += "\"#{type}\""
1679
+ count += 1
1680
+ else
1681
+ jssh_command += ",\"#{type}\""
1682
+ end
1683
+ end
1684
+ jssh_command += ");"
1685
+ else
1686
+ jssh_command += "var types = null;"
1687
+ end
1688
+
1689
+ if(@container.class == FireWatir::Firefox || @container.class == Frame)
1690
+
1691
+ jssh_command += "for(var i=0; i<elements_#{tag}.length; i++)
1692
+ {
1693
+
1694
+ var element = elements_#{tag}[i];"
1695
+ else
1696
+ jssh_command += "for(var i=0; i<elements_#{@@current_level}_#{tag}.length; i++)
1697
+ {
1698
+
1699
+ var element = elements_#{@@current_level}_#{tag}[i];"
1700
+ end
1701
+
1702
+ jssh_command += "
1703
+ var same_type = false;
1704
+ if(types)
1705
+ {
1706
+ for(var j=0; j<types.length; j++)
1707
+ {
1708
+ if(types[j] == element.type || types[j] == element.tagName)
1709
+ {
1710
+ same_type = true;
1711
+ break;
1712
+ }
1713
+ }
1714
+ }
1715
+ else
1716
+ {
1717
+ same_type = true;
1718
+ }
1719
+ if(same_type == true)
1720
+ {
1721
+ arr_coll_#{tag}_#{@@current_level}.push(element);
1722
+ }
1723
+ }
1724
+ arr_coll_#{tag}_#{@@current_level}.length;"
1725
+
1726
+ # Remove \n that are there in the string as a result of pressing enter while formatting.
1727
+ jssh_command.gsub!(/\n/, "")
1728
+ #puts jssh_command
1729
+ jssh_socket.send("#{jssh_command};\n", 0)
1730
+ length = read_socket().to_i;
1731
+ #puts "elements length is in locate_tagged_elements is : #{length}"
1732
+
1733
+ elements = Array.new(length)
1734
+ for i in 0..length - 1 do
1735
+ elements[i] = "arr_coll_#{tag}_#{@@current_level}[#{i}]"
1736
+ end
1737
+ @@current_level = @@current_level + 1
1738
+ return elements
1739
+ end
1740
+ private:locate_tagged_elements
1741
+
1742
+ #
1743
+ # Description:
1744
+ # Gets the length of elements of same tag and type found on the page.
1745
+ #
1746
+ # Ouput:
1747
+ # Count of elements found on the page.
1748
+ #
1749
+ def length
1750
+ #puts @element_objects.length
1751
+ return @element_objects.length
1752
+ end
1753
+
1754
+ #
1755
+ # Description:
1756
+ # Iterate over the elements of same tag and type found on the page.
1757
+ #
1758
+ def each
1759
+ for i in 0..@element_objects.length - 1
1760
+ yield @element_objects[i]
1761
+ end
1762
+ end
1763
+
1764
+ #
1765
+ # Description:
1766
+ # Accesses nth element of same tag and type found on the page.
1767
+ #
1768
+ # Input:
1769
+ # n - index of element (1 based)
1770
+ #
1771
+ def [](n)
1772
+ return @element_objects[n-1]
1773
+ end
1774
+
1775
+ end