jarib-celerity 0.0.5
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.
- 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
|