firewatir 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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