jarib-celerity 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +42 -0
- data/License.txt +621 -0
- data/README.txt +64 -0
- data/Rakefile +12 -0
- data/lib/celerity.rb +59 -0
- data/lib/celerity/browser.rb +410 -0
- data/lib/celerity/clickable_element.rb +26 -0
- data/lib/celerity/collections.rb +148 -0
- data/lib/celerity/container.rb +488 -0
- data/lib/celerity/default_viewer.rb +10 -0
- data/lib/celerity/disabled_element.rb +27 -0
- data/lib/celerity/element.rb +241 -0
- data/lib/celerity/element_collections.rb +68 -0
- data/lib/celerity/element_locator.rb +167 -0
- data/lib/celerity/elements/button.rb +34 -0
- data/lib/celerity/elements/file_field.rb +17 -0
- data/lib/celerity/elements/form.rb +16 -0
- data/lib/celerity/elements/frame.rb +53 -0
- data/lib/celerity/elements/image.rb +57 -0
- data/lib/celerity/elements/label.rb +9 -0
- data/lib/celerity/elements/link.rb +12 -0
- data/lib/celerity/elements/meta.rb +6 -0
- data/lib/celerity/elements/non_control_elements.rb +93 -0
- data/lib/celerity/elements/option.rb +18 -0
- data/lib/celerity/elements/radio_check.rb +85 -0
- data/lib/celerity/elements/select_list.rb +81 -0
- data/lib/celerity/elements/table.rb +117 -0
- data/lib/celerity/elements/table_cell.rb +28 -0
- data/lib/celerity/elements/table_elements.rb +41 -0
- data/lib/celerity/elements/table_row.rb +36 -0
- data/lib/celerity/elements/text_field.rb +127 -0
- data/lib/celerity/exception.rb +40 -0
- data/lib/celerity/extra/method_generator.rb +158 -0
- data/lib/celerity/htmlunit.rb +41 -0
- data/lib/celerity/htmlunit/commons-codec-1.3.jar +0 -0
- data/lib/celerity/htmlunit/commons-collections-3.2.1.jar +0 -0
- data/lib/celerity/htmlunit/commons-httpclient-3.1.jar +0 -0
- data/lib/celerity/htmlunit/commons-io-1.4.jar +0 -0
- data/lib/celerity/htmlunit/commons-lang-2.4.jar +0 -0
- data/lib/celerity/htmlunit/commons-logging-1.1.1.jar +0 -0
- data/lib/celerity/htmlunit/cssparser-0.9.5.jar +0 -0
- data/lib/celerity/htmlunit/htmlunit-2.4-SNAPSHOT.jar +0 -0
- data/lib/celerity/htmlunit/htmlunit-core-js-2.4-SNAPSHOT.jar +0 -0
- data/lib/celerity/htmlunit/nekohtml-1.9.10-20081209.100757-4.jar +0 -0
- data/lib/celerity/htmlunit/sac-1.3.jar +0 -0
- data/lib/celerity/htmlunit/serializer-2.7.1.jar +0 -0
- data/lib/celerity/htmlunit/xalan-2.7.1.jar +0 -0
- data/lib/celerity/htmlunit/xercesImpl-2.8.1.jar +0 -0
- data/lib/celerity/htmlunit/xml-apis-1.3.04.jar +0 -0
- data/lib/celerity/identifier.rb +11 -0
- data/lib/celerity/input_element.rb +25 -0
- data/lib/celerity/listener.rb +106 -0
- data/lib/celerity/resources/no_viewer.png +0 -0
- data/lib/celerity/util.rb +79 -0
- data/lib/celerity/version.rb +9 -0
- data/lib/celerity/watir_compatibility.rb +85 -0
- data/tasks/benchmark.rake +4 -0
- data/tasks/deployment.rake +43 -0
- data/tasks/environment.rake +7 -0
- data/tasks/fix.rake +25 -0
- data/tasks/jar.rake +57 -0
- data/tasks/rdoc.rake +4 -0
- data/tasks/rspec.rake +30 -0
- data/tasks/simple_ci.rake +94 -0
- data/tasks/snapshot.rake +26 -0
- data/tasks/specserver.rake +21 -0
- data/tasks/website.rake +17 -0
- data/tasks/yard.rake +5 -0
- metadata +129 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module Celerity
|
2
|
+
#
|
3
|
+
# Input: Button
|
4
|
+
#
|
5
|
+
# Class representing button elements
|
6
|
+
#
|
7
|
+
class Button < InputElement
|
8
|
+
TAGS = [ Identifier.new('button'),
|
9
|
+
Identifier.new('input', :type => %w[submit reset image button]) ]
|
10
|
+
# A little wierd attribute list due to button being both <button> and <input type="submit|reset|image|button" />
|
11
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:type, :disabled, :tabindex, :accesskey, :onfocus, :onblur] | [:src, :usemap, :ismap]
|
12
|
+
DEFAULT_HOW = :value
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
def locate
|
16
|
+
# ugly..
|
17
|
+
# this is done to make <button> and <input>-buttons look similar
|
18
|
+
if (val = @conditions[:value])
|
19
|
+
locator = ElementLocator.new(@container, self.class)
|
20
|
+
button_ident = Identifier.new('button')
|
21
|
+
button_ident.text = val
|
22
|
+
input_ident = Identifier.new('input', :type => %w[submit reset image button], :value => [val])
|
23
|
+
locator.idents = [button_ident, input_ident]
|
24
|
+
conditions = @conditions.dup
|
25
|
+
conditions.delete(:value)
|
26
|
+
@object = locator.find_by_conditions(conditions)
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Celerity
|
2
|
+
# For fields that accept file uploads
|
3
|
+
class FileField < InputElement
|
4
|
+
TAGS = [ Identifier.new('input', :type => %w[file]) ]
|
5
|
+
DEFAULT_HOW = :name
|
6
|
+
|
7
|
+
# Set the file field to the given path
|
8
|
+
def set(path)
|
9
|
+
assert_exists
|
10
|
+
path = path.to_s
|
11
|
+
@container.update_page @object.setValueAttribute(path)
|
12
|
+
unless @object.getContentType
|
13
|
+
@object.setContentType(Celerity::Util.content_type_for(path))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Celerity
|
2
|
+
class Form < Element
|
3
|
+
include Container
|
4
|
+
TAGS = [Identifier.new('form')]
|
5
|
+
# HTML 4.01 Transitional DTD
|
6
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:action, :method, :enctype, :accept, :name, :onsubmit, :onreset, :target, :'accept-charset']
|
7
|
+
DEFAULT_HOW = :name
|
8
|
+
|
9
|
+
# Submits the form.
|
10
|
+
def submit
|
11
|
+
assert_exists
|
12
|
+
@container.update_page @object.submit(nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Celerity
|
2
|
+
class Frame < Element
|
3
|
+
include Container
|
4
|
+
attr_accessor :page
|
5
|
+
|
6
|
+
TAGS = [Identifier.new('frame'), Identifier.new('iframe')]
|
7
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
|
8
|
+
DEFAULT_HOW = :name
|
9
|
+
|
10
|
+
# Override the default locate to handle frame and inline frames.
|
11
|
+
# @api private
|
12
|
+
def locate
|
13
|
+
super
|
14
|
+
if @object
|
15
|
+
@inline_frame_object = @object.getEnclosedWindow.getFrameElement
|
16
|
+
if (frame = @object.getEnclosedPage.getDocumentElement)
|
17
|
+
@object = frame
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Override assert_exists to raise UnknownFrameException (for Watir compatibility)
|
23
|
+
# @api private
|
24
|
+
def assert_exists
|
25
|
+
locate
|
26
|
+
unless @object
|
27
|
+
raise UnknownFrameException, "unable to locate frame, using #{identifier_string}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_page(value)
|
32
|
+
@browser.page = value.getEnclosingWindow.getTopWindow.getEnclosedPage
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
assert_exists
|
37
|
+
create_string(@inline_frame_object)
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(meth, *args, &blk)
|
41
|
+
meth = selector_to_attribute(meth)
|
42
|
+
if self.class::ATTRIBUTES.include?(meth)
|
43
|
+
assert_exists
|
44
|
+
@inline_frame_object.getAttributeValue(meth.to_s)
|
45
|
+
else
|
46
|
+
Log.warn "Element\#method_missing calling super with #{meth.inspect}"
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Celerity
|
2
|
+
|
3
|
+
class Image < Element
|
4
|
+
include ClickableElement
|
5
|
+
|
6
|
+
TAGS = [ Identifier.new('img') ]
|
7
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:src, :alt, :longdesc, :name, :height, :width, :usemap, :ismap, :align, :border, :hspace, :vspace]
|
8
|
+
DEFAULT_HOW = :src
|
9
|
+
|
10
|
+
# returns the file created date of the image
|
11
|
+
def file_created_date
|
12
|
+
assert_exists
|
13
|
+
web_response = @object.getWebResponse(true)
|
14
|
+
Time.parse(web_response.getResponseHeaderValue("Last-Modified").to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
# returns the filesize of the image
|
18
|
+
def file_size
|
19
|
+
assert_exists
|
20
|
+
web_response = @object.getWebResponse(true)
|
21
|
+
web_response.getResponseBody.length
|
22
|
+
end
|
23
|
+
|
24
|
+
# returns the width in pixels of the image, as a string
|
25
|
+
def width
|
26
|
+
assert_exists
|
27
|
+
@object.getWidth
|
28
|
+
end
|
29
|
+
|
30
|
+
# returns the height in pixels of the image, as a string
|
31
|
+
def height
|
32
|
+
assert_exists
|
33
|
+
@object.getHeight
|
34
|
+
end
|
35
|
+
|
36
|
+
# returns true if the image is loaded
|
37
|
+
def loaded?
|
38
|
+
assert_exists
|
39
|
+
begin
|
40
|
+
@object.getImageReader
|
41
|
+
true
|
42
|
+
rescue
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Saves the image to the given file
|
48
|
+
def save(filename)
|
49
|
+
assert_exists
|
50
|
+
image_reader = @object.getImageReader
|
51
|
+
file = java.io.File.new(filename)
|
52
|
+
buffered_image = image_reader.read(0);
|
53
|
+
javax.imageio.ImageIO.write(buffered_image, image_reader.getFormatName(), file);
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Celerity
|
2
|
+
class Link < Element
|
3
|
+
include ClickableElement
|
4
|
+
|
5
|
+
TAGS = [ Identifier.new('a') ]
|
6
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:charset, :type, :name, :href, :hreflang,
|
7
|
+
:target, :rel, :rev, :accesskey, :shape,
|
8
|
+
:coords, :tabindex, :onfocus, :onblur]
|
9
|
+
DEFAULT_HOW = :href
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Celerity
|
2
|
+
|
3
|
+
# Superclass for for Span, Pre, Div, H1, ...
|
4
|
+
class NonControlElement < Element
|
5
|
+
include Exception
|
6
|
+
include ClickableElement
|
7
|
+
|
8
|
+
ATTRIBUTES = BASE_ATTRIBUTES
|
9
|
+
DEFAULT_HOW = :id
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# classes ordered alphabetically
|
14
|
+
#
|
15
|
+
|
16
|
+
class Area < NonControlElement
|
17
|
+
ATTRIBUTES = ATTRIBUTES | [:shape, :coords, :href, :nohref, :alt, :tabindex, :accesskey, :onfocus, :onblur]
|
18
|
+
TAGS = [ Identifier.new('area') ]
|
19
|
+
end
|
20
|
+
|
21
|
+
class Dd < NonControlElement
|
22
|
+
TAGS = [ Identifier.new('dd')]
|
23
|
+
end
|
24
|
+
|
25
|
+
class Div < NonControlElement
|
26
|
+
TAGS = [ Identifier.new('div')]
|
27
|
+
end
|
28
|
+
|
29
|
+
class Dl < NonControlElement
|
30
|
+
TAGS = [ Identifier.new('dl')]
|
31
|
+
end
|
32
|
+
|
33
|
+
class Dt < NonControlElement
|
34
|
+
TAGS = [ Identifier.new('dt')]
|
35
|
+
end
|
36
|
+
|
37
|
+
class H1 < NonControlElement
|
38
|
+
TAGS = [ Identifier.new('h1') ]
|
39
|
+
end
|
40
|
+
|
41
|
+
class H2 < NonControlElement
|
42
|
+
TAGS = [ Identifier.new('h2') ]
|
43
|
+
end
|
44
|
+
|
45
|
+
class H3 < NonControlElement
|
46
|
+
TAGS = [ Identifier.new('h3') ]
|
47
|
+
end
|
48
|
+
|
49
|
+
class H4 < NonControlElement
|
50
|
+
TAGS = [ Identifier.new('h4') ]
|
51
|
+
end
|
52
|
+
|
53
|
+
class H5 < NonControlElement
|
54
|
+
TAGS = [ Identifier.new('h5') ]
|
55
|
+
end
|
56
|
+
|
57
|
+
class H6 < NonControlElement
|
58
|
+
TAGS = [ Identifier.new('h6') ]
|
59
|
+
end
|
60
|
+
|
61
|
+
class Li < NonControlElement
|
62
|
+
TAGS = [ Identifier.new('li') ]
|
63
|
+
end
|
64
|
+
|
65
|
+
class Map < NonControlElement
|
66
|
+
TAGS = [ Identifier.new('map') ]
|
67
|
+
end
|
68
|
+
|
69
|
+
class Ol < NonControlElement
|
70
|
+
TAGS = [ Identifier.new('ol') ]
|
71
|
+
end
|
72
|
+
|
73
|
+
class P < NonControlElement
|
74
|
+
TAGS = [ Identifier.new('p') ]
|
75
|
+
end
|
76
|
+
|
77
|
+
class Pre < NonControlElement
|
78
|
+
TAGS = [ Identifier.new('pre')]
|
79
|
+
end
|
80
|
+
|
81
|
+
class Span < NonControlElement
|
82
|
+
TAGS = [ Identifier.new('span') ]
|
83
|
+
end
|
84
|
+
|
85
|
+
# class Title < NonControlElement
|
86
|
+
# TAGS = [ Identifier.new('title') ]
|
87
|
+
# end
|
88
|
+
|
89
|
+
class Ul < NonControlElement
|
90
|
+
TAGS = [ Identifier.new('ul') ]
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Celerity
|
2
|
+
# Represents a select list option.
|
3
|
+
class Option < Element
|
4
|
+
include ClickableElement
|
5
|
+
include DisabledElement
|
6
|
+
|
7
|
+
TAGS = [ Identifier.new('option')]
|
8
|
+
ATTRIBUTES = BASE_ATTRIBUTES | [:selected, :disabled, :label, :value]
|
9
|
+
DEFAULT_HOW = :text
|
10
|
+
|
11
|
+
alias_method :select, :click
|
12
|
+
|
13
|
+
def selected?
|
14
|
+
assert_exists
|
15
|
+
@object.isSelected
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Celerity
|
2
|
+
# Common superclass for radios and check boxes.
|
3
|
+
class RadioCheckCommon < InputElement
|
4
|
+
DEFAULT_HOW = :name
|
5
|
+
|
6
|
+
# these can optionally take a value parameter as a third arg, so needs
|
7
|
+
# to be special-handled.
|
8
|
+
def initialize(container, type, *args)
|
9
|
+
@type = type
|
10
|
+
case args.size
|
11
|
+
when 2
|
12
|
+
super(container, args[0] => args[1])
|
13
|
+
when 3
|
14
|
+
super(container, args[0] => args[1], :value => args[2])
|
15
|
+
else
|
16
|
+
super(container, *args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns true if the element is checked
|
21
|
+
# @return [true, false]
|
22
|
+
def set?
|
23
|
+
assert_exists
|
24
|
+
@object.isChecked
|
25
|
+
end
|
26
|
+
alias_method :checked?, :set?
|
27
|
+
|
28
|
+
def clear
|
29
|
+
set(false)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# This class is the celerity representation of a radio button.
|
34
|
+
class Radio < RadioCheckCommon
|
35
|
+
TAGS = [Identifier.new('input', :type => %w[radio])]
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def initialize(container, *args)
|
39
|
+
super(container, %w[radio], *args)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set the radio button to the given value.
|
43
|
+
#
|
44
|
+
# radio.set? # => false
|
45
|
+
# radio.set
|
46
|
+
# radio.set? # => true
|
47
|
+
# radio.set(false)
|
48
|
+
# radio.set? # => false
|
49
|
+
def set(value = true)
|
50
|
+
assert_exists
|
51
|
+
assert_enabled
|
52
|
+
@container.update_page(value ? @object.click : @object.setChecked(value))
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# This class is the celerity representation of a check box.
|
58
|
+
#
|
59
|
+
class CheckBox < RadioCheckCommon
|
60
|
+
TAGS = [Identifier.new('input', :type => %w[checkbox])]
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
def initialize(container, *args)
|
64
|
+
super(container, %w[checkbox], *args)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Set the checkbox to the given value.
|
68
|
+
#
|
69
|
+
# checkbox.set? # => false
|
70
|
+
# checkbox.set
|
71
|
+
# checkbox.set? # => true
|
72
|
+
# checkbox.set(false)
|
73
|
+
# checkbox.set? # => false
|
74
|
+
def set(value = true)
|
75
|
+
assert_exists
|
76
|
+
assert_enabled
|
77
|
+
|
78
|
+
if (value && !set?) || (!value && set?)
|
79
|
+
Log.debug(@object.inspect)
|
80
|
+
@container.update_page(@object.click)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Celerity
|
2
|
+
class SelectList < InputElement
|
3
|
+
TAGS = [ Identifier.new('select') ]
|
4
|
+
DEFAULT_HOW = :name
|
5
|
+
|
6
|
+
# @return [Array<String>] An array of strings representing the text value of the select list's options.
|
7
|
+
def options
|
8
|
+
assert_exists
|
9
|
+
@object.getOptions.map { |e| e.asText }
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Array<String>] An array of strings representing the text value of the currently selected options.
|
13
|
+
def selected_options
|
14
|
+
assert_exists
|
15
|
+
@object.getSelectedOptions.map { |e| e.asText }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Clear all selected options
|
19
|
+
# TODO: should update page for each option changed?
|
20
|
+
def clear
|
21
|
+
# assert_exists called by SelectList#type here
|
22
|
+
@object.getSelectedOptions.each { |e| e.setSelected(false) } unless type() == 'select-one'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Select the option(s) matching the given value.
|
26
|
+
# If several options match the value given, all will be selected.
|
27
|
+
#
|
28
|
+
# @param [String, Regexp] value A value.
|
29
|
+
# @raise [Celerity::Exception::NoValueFoundException] if the value does not exist.
|
30
|
+
def select(value)
|
31
|
+
assert_exists
|
32
|
+
raise NoValueFoundException, "unknown option with value #{value.inspect} for select_list #{@conditions.inspect}" unless include?(value)
|
33
|
+
@object.getOptions.select { |e| matches?(e.asText, value) }.each do |option|
|
34
|
+
@container.update_page option.click
|
35
|
+
end
|
36
|
+
end
|
37
|
+
alias_method :set, :select
|
38
|
+
|
39
|
+
# Returns true if the select list has one or more options matching the given value.
|
40
|
+
#
|
41
|
+
# @param [String, Regexp] value A value.
|
42
|
+
# @return [true, false]
|
43
|
+
def include?(value)
|
44
|
+
assert_exists
|
45
|
+
!!@object.getOptions.find { |e| matches?(e.asText, value) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns true if any of the selected options match the given value.
|
49
|
+
#
|
50
|
+
# @param [String, Regexp] value A value.
|
51
|
+
# @raise [Celerity::Exception::UnknownObjectException] if the value does not exist.
|
52
|
+
# @return [true, false]
|
53
|
+
def selected?(value)
|
54
|
+
assert_exists
|
55
|
+
raise UnknownObjectException, "unknown option with value #{value.inspect} for select_list #{@conditions.inspect}" unless include?(value)
|
56
|
+
!!@object.getOptions.find { |e| matches?(e.asText, value) && e.isSelected }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns 'select-multiple' if the select list has the 'multiple' attribute,
|
60
|
+
# defined, otherwise 'select-one'.
|
61
|
+
#
|
62
|
+
# @return [String]
|
63
|
+
# TODO: Move to watir_compatibility or delete it 2008-05-23 Alexander
|
64
|
+
def type
|
65
|
+
assert_exists
|
66
|
+
'select-' + (@object.isAttributeDefined('multiple') ? 'multiple' : 'one')
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the value of the first selected option in the select list.
|
70
|
+
# Returns nil if no option is selected.
|
71
|
+
#
|
72
|
+
# @return [String, nil]
|
73
|
+
def value
|
74
|
+
assert_exists
|
75
|
+
if (optn = @object.getSelectedOptions.to_a.first)
|
76
|
+
optn.getValueAttribute
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|