ae_page_objects 0.4.1 → 0.5.1
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/lib/ae_page_objects.rb +1 -0
- data/lib/ae_page_objects/document.rb +6 -1
- data/lib/ae_page_objects/element.rb +1 -1
- data/lib/ae_page_objects/elements/collection.rb +26 -27
- data/lib/ae_page_objects/util/singleton.rb +1 -0
- data/lib/ae_page_objects/version.rb +1 -1
- data/lib/ae_page_objects/window.rb +126 -0
- metadata +7 -52
data/lib/ae_page_objects.rb
CHANGED
@@ -23,6 +23,7 @@ module AePageObjects
|
|
23
23
|
autoload :Visitable, 'ae_page_objects/concerns/visitable'
|
24
24
|
end
|
25
25
|
|
26
|
+
autoload :Window, 'ae_page_objects/window'
|
26
27
|
autoload :Node, 'ae_page_objects/node'
|
27
28
|
autoload :Document, 'ae_page_objects/document'
|
28
29
|
autoload :Element, 'ae_page_objects/element'
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module AePageObjects
|
2
2
|
class Document < Node
|
3
3
|
include Concerns::Visitable
|
4
|
+
|
5
|
+
attr_reader :window
|
4
6
|
|
5
7
|
def initialize
|
6
8
|
super(Capybara.current_session)
|
7
|
-
end
|
8
9
|
|
10
|
+
@window = Window.current
|
11
|
+
@window.current_document = self
|
12
|
+
end
|
13
|
+
|
9
14
|
def document
|
10
15
|
self
|
11
16
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
module AePageObjects
|
2
2
|
class Collection < Element
|
3
|
+
include Enumerable
|
4
|
+
|
3
5
|
class << self
|
4
6
|
attr_accessor :item_class
|
5
7
|
|
6
|
-
|
8
|
+
def default_item_locator
|
9
|
+
@default_item_locator ||= [:xpath, ".//*"]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
7
13
|
def inherited(subclass)
|
8
14
|
subclass.item_class = self.item_class
|
9
15
|
end
|
@@ -15,11 +21,15 @@ module AePageObjects
|
|
15
21
|
self.class.item_class
|
16
22
|
end
|
17
23
|
|
24
|
+
def item_xpath
|
25
|
+
@item_xpath ||= Capybara::Selector.normalize(*eval_locator(@item_locator)).xpaths.first
|
26
|
+
end
|
27
|
+
|
18
28
|
def at(index, &block)
|
19
29
|
if index >= size || index < 0
|
20
30
|
nil
|
21
31
|
else
|
22
|
-
|
32
|
+
item_at(index, &block)
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
@@ -33,43 +43,32 @@ module AePageObjects
|
|
33
43
|
end
|
34
44
|
end
|
35
45
|
|
36
|
-
def all
|
37
|
-
[].tap do |all|
|
38
|
-
self.each { |item| all << item }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
46
|
def size
|
43
|
-
node.all(:xpath,
|
44
|
-
end
|
45
|
-
|
46
|
-
def first(&block)
|
47
|
-
self.at(0, &block)
|
47
|
+
node.all(:xpath, item_xpath).size
|
48
48
|
end
|
49
49
|
|
50
50
|
def last(&block)
|
51
51
|
self.at(size - 1, &block)
|
52
52
|
end
|
53
|
-
|
54
|
-
def add_more(&block)
|
55
|
-
append
|
56
|
-
last(&block)
|
57
|
-
end
|
58
53
|
|
59
|
-
|
60
|
-
@row_xpath || ".//*[contains(@class, 'item-list')]//*[contains(@class,'row') and not(contains(@style,'display'))]"
|
61
|
-
end
|
62
|
-
|
63
|
-
protected
|
54
|
+
private
|
64
55
|
|
65
56
|
def configure(options)
|
66
57
|
super
|
67
58
|
|
68
|
-
@
|
59
|
+
@item_locator = options.delete(:item_locator) || self.class.default_item_locator
|
69
60
|
end
|
70
|
-
|
71
|
-
def
|
72
|
-
|
61
|
+
|
62
|
+
def item_at(index, &block)
|
63
|
+
ElementProxy.new(item_class_at(index), self, :name => index, :locator => item_locator_at(index), &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def item_class_at(index)
|
67
|
+
item_class
|
68
|
+
end
|
69
|
+
|
70
|
+
def item_locator_at(index)
|
71
|
+
[:xpath, "#{item_xpath}[#{index + 1}]"]
|
73
72
|
end
|
74
73
|
end
|
75
74
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module AePageObjects
|
2
|
+
class Window
|
3
|
+
|
4
|
+
class Registry < Hash
|
5
|
+
def [](window_or_handle)
|
6
|
+
if window_or_handle.is_a?(Window)
|
7
|
+
super(window_or_handle.handle)
|
8
|
+
else
|
9
|
+
super(window_or_handle)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def add(window)
|
14
|
+
self[window.handle] = window
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove(window)
|
18
|
+
self.delete(window.handle)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class HandleManager
|
23
|
+
def self.all
|
24
|
+
browser.window_handles
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.current
|
28
|
+
# Accessing browser.window_handle tries to find an existing page, which will blow up
|
29
|
+
# if there isn't one. So... we look at the collection first as a guard.
|
30
|
+
if all.empty?
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
browser.window_handle
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.switch_to(handle)
|
38
|
+
browser.switch_to.window(handle)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.browser
|
42
|
+
Capybara.current_session.driver.browser
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.close(handle)
|
46
|
+
all_handles_before_close = all()
|
47
|
+
more_than_one_window = (all_handles_before_close.size > 1)
|
48
|
+
|
49
|
+
# We must protect against closing the last window as doing so will quit the entire browser
|
50
|
+
# which would mess up subsequent tests.
|
51
|
+
# http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebDriver.html#close()
|
52
|
+
return false unless more_than_one_window
|
53
|
+
|
54
|
+
current_handle_before_switch = current
|
55
|
+
|
56
|
+
# switch to the window to close
|
57
|
+
switch_to(handle)
|
58
|
+
|
59
|
+
browser.close
|
60
|
+
|
61
|
+
# need to switch back to something. Use whatever was switched from originally unless we just
|
62
|
+
# closed that window, in which case just pick something else.
|
63
|
+
switch_to(current_handle_before_switch == handle ? all.first : current_handle_before_switch)
|
64
|
+
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def registry
|
71
|
+
@registry ||= Registry.new
|
72
|
+
end
|
73
|
+
|
74
|
+
def close_all
|
75
|
+
all.each(&:close)
|
76
|
+
end
|
77
|
+
|
78
|
+
def all
|
79
|
+
HandleManager.all.map do |handle|
|
80
|
+
find(handle)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def find(handle)
|
85
|
+
registry[handle] || create(handle)
|
86
|
+
end
|
87
|
+
|
88
|
+
def current
|
89
|
+
current_handle = HandleManager.current
|
90
|
+
|
91
|
+
find(current_handle) if current_handle
|
92
|
+
end
|
93
|
+
|
94
|
+
def create(handle)
|
95
|
+
new(registry, handle)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
attr_reader :current_document, :handle
|
100
|
+
|
101
|
+
def initialize(registry, handle)
|
102
|
+
@registry = registry
|
103
|
+
@handle = handle
|
104
|
+
@current_document = nil
|
105
|
+
|
106
|
+
@registry.add(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
def current_document=(document)
|
110
|
+
@current_document.send(:stale!) if @current_document
|
111
|
+
@current_document = document
|
112
|
+
end
|
113
|
+
|
114
|
+
def switch_to
|
115
|
+
HandleManager.switch_to(handle)
|
116
|
+
current_document
|
117
|
+
end
|
118
|
+
|
119
|
+
def close
|
120
|
+
if HandleManager.close(@handle)
|
121
|
+
self.current_document = nil
|
122
|
+
@registry.remove(self)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ae_page_objects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 1
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Donnie Tognazzini
|
@@ -15,10 +15,9 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-
|
18
|
+
date: 2013-10-26 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
type: :runtime
|
22
21
|
name: capybara
|
23
22
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
23
|
none: false
|
@@ -30,54 +29,9 @@ dependencies:
|
|
30
29
|
- 1
|
31
30
|
- 1
|
32
31
|
version: "1.1"
|
33
|
-
requirement: *id001
|
34
|
-
prerelease: false
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
type: :development
|
37
|
-
name: appraisal
|
38
|
-
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 9
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
- 5
|
47
|
-
- 1
|
48
|
-
version: 0.5.1
|
49
|
-
requirement: *id002
|
50
|
-
prerelease: false
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
type: :development
|
53
|
-
name: mocha
|
54
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
|
-
requirements:
|
57
|
-
- - "="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
hash: 45
|
60
|
-
segments:
|
61
|
-
- 0
|
62
|
-
- 13
|
63
|
-
- 3
|
64
|
-
version: 0.13.3
|
65
|
-
requirement: *id003
|
66
|
-
prerelease: false
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
type: :development
|
69
|
-
name: selenium-webdriver
|
70
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
hash: 3
|
76
|
-
segments:
|
77
|
-
- 0
|
78
|
-
version: "0"
|
79
|
-
requirement: *id004
|
80
32
|
prerelease: false
|
33
|
+
type: :runtime
|
34
|
+
requirement: *id001
|
81
35
|
description: Capybara Page Objects pattern
|
82
36
|
email:
|
83
37
|
- engineering@appfolio.com
|
@@ -113,6 +67,7 @@ files:
|
|
113
67
|
- lib/ae_page_objects/util/internal_helpers.rb
|
114
68
|
- lib/ae_page_objects/util/singleton.rb
|
115
69
|
- lib/ae_page_objects/version.rb
|
70
|
+
- lib/ae_page_objects/window.rb
|
116
71
|
homepage: http://github.com/appfolio/ae_page_objects
|
117
72
|
licenses:
|
118
73
|
- MIT
|