page_magic 0.10.0 → 0.11.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/VERSION +1 -1
- data/lib/ext/string.rb +9 -0
- data/lib/page_magic/element.rb +54 -62
- data/lib/page_magic/element_context.rb +4 -4
- data/lib/page_magic/elements.rb +23 -44
- data/lib/page_magic/exceptions.rb +10 -0
- data/lib/page_magic/page_magic.rb +5 -31
- data/lib/page_magic/session.rb +10 -6
- data/lib/page_magic.rb +1 -1
- data/page_magic.gemspec +12 -7
- data/spec/element_context_spec.rb +25 -3
- data/spec/element_spec.rb +96 -21
- data/spec/member_methods_spec.rb +0 -22
- data/spec/{elements_spec.rb → page_magic/elements/elements_spec.rb} +76 -85
- data/spec/page_magic/usage/defining_page_elements_spec.rb +8 -0
- data/spec/page_magic/usage/defining_pages_spec.rb +88 -0
- data/spec/page_magic/usage/include_page_magic_spec.rb +20 -0
- data/spec/page_magic/usage/interacting_with_pages_spec.rb +56 -0
- data/spec/page_magic/usage/starting_a_session_spec.rb +63 -0
- data/spec/spec_helper.rb +35 -2
- metadata +15 -10
- data/lib/page_magic/section.rb +0 -105
- data/spec/page_magic_spec.rb +0 -168
- data/spec/section_spec.rb +0 -106
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require 'spec_helper'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0.alpha
|
data/lib/ext/string.rb
ADDED
data/lib/page_magic/element.rb
CHANGED
@@ -1,43 +1,28 @@
|
|
1
|
-
require 'watir-webdriver'
|
2
1
|
module PageMagic
|
3
2
|
|
4
|
-
class UnsupportedSelectorException < Exception
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
3
|
class Element
|
4
|
+
attr_reader :type, :name, :selector, :browser_element
|
9
5
|
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
include AjaxSupport
|
14
|
-
|
15
|
-
attr_reader :type, :name, :selector, :before_hook, :after_hook, :browser_element, :locator
|
16
|
-
|
17
|
-
class << self
|
18
|
-
def default_before_hook
|
19
|
-
@default_before_hook ||= Proc.new {}
|
20
|
-
end
|
21
|
-
|
22
|
-
def default_after_hook
|
23
|
-
@default_after_hook ||= Proc.new {}
|
24
|
-
end
|
25
|
-
end
|
6
|
+
include AjaxSupport, Elements
|
26
7
|
|
27
8
|
def initialize name, parent_page_element, type=nil, selector=nil, &block
|
28
|
-
|
29
|
-
|
30
|
-
@browser_element = parent_page_element.browser_element
|
9
|
+
if selector.is_a?(Hash)
|
10
|
+
@selector = selector
|
31
11
|
else
|
32
|
-
@browser_element =
|
12
|
+
@browser_element = selector
|
33
13
|
end
|
34
14
|
|
35
|
-
@type = type
|
36
|
-
|
15
|
+
@parent_page_element, @type, @name = parent_page_element, type, name.to_s.downcase.to_sym
|
16
|
+
instance_eval &block if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def selector selector=nil
|
20
|
+
return @selector unless selector
|
37
21
|
@selector = selector
|
22
|
+
end
|
38
23
|
|
39
|
-
|
40
|
-
|
24
|
+
def section?
|
25
|
+
!element_definitions.empty?
|
41
26
|
end
|
42
27
|
|
43
28
|
def session
|
@@ -45,50 +30,57 @@ module PageMagic
|
|
45
30
|
end
|
46
31
|
|
47
32
|
def before &block
|
33
|
+
return @before_hook unless block
|
48
34
|
@before_hook = block
|
49
35
|
end
|
50
36
|
|
51
37
|
def after &block
|
38
|
+
return @after_hook unless block
|
52
39
|
@after_hook = block
|
53
40
|
end
|
54
41
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
when :label
|
64
|
-
@browser_element.find_field(selector)
|
65
|
-
when :text
|
66
|
-
if @type == :link
|
67
|
-
@browser_element.find_link(selector)
|
68
|
-
elsif @type == :button
|
69
|
-
@browser_element.find_button(selector)
|
70
|
-
else
|
71
|
-
raise UnsupportedSelectorException
|
72
|
-
end
|
73
|
-
when :css
|
74
|
-
@browser_element.find(:css, selector)
|
75
|
-
else
|
76
|
-
raise UnsupportedSelectorException
|
77
|
-
|
42
|
+
def method_missing method, *args
|
43
|
+
begin
|
44
|
+
ElementContext.new(self, @browser_element, self, *args).send(method, args.first)
|
45
|
+
rescue ElementMissingException
|
46
|
+
begin
|
47
|
+
@browser_element.send(method, *args)
|
48
|
+
rescue
|
49
|
+
super
|
78
50
|
end
|
79
|
-
else
|
80
|
-
@browser_element
|
81
51
|
end
|
82
52
|
end
|
83
53
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
54
|
+
def browser_element *args
|
55
|
+
return @browser_element if @browser_element
|
56
|
+
raise UndefinedSelectorException, "Pass a selector/define one on the class" unless @selector
|
57
|
+
if @selector
|
58
|
+
method, selector = @selector.to_a.flatten
|
59
|
+
browser_element = @parent_page_element.browser_element
|
60
|
+
@browser_element = case method
|
61
|
+
when :id
|
62
|
+
browser_element.find("##{selector}")
|
63
|
+
when :xpath
|
64
|
+
browser_element.find(:xpath, selector)
|
65
|
+
when :name
|
66
|
+
browser_element.find("*[name='#{selector}']")
|
67
|
+
when :label
|
68
|
+
browser_element.find_field(selector)
|
69
|
+
when :text
|
70
|
+
if @type == :link
|
71
|
+
browser_element.find_link(selector)
|
72
|
+
elsif @type == :button
|
73
|
+
browser_element.find_button(selector)
|
74
|
+
else
|
75
|
+
raise UnsupportedSelectorException
|
76
|
+
end
|
77
|
+
when :css
|
78
|
+
browser_element.find(:css, selector)
|
79
|
+
else
|
80
|
+
raise UnsupportedSelectorException
|
81
|
+
end
|
82
|
+
end
|
83
|
+
@browser_element
|
92
84
|
end
|
93
85
|
end
|
94
86
|
end
|
@@ -35,15 +35,15 @@ module PageMagic
|
|
35
35
|
element_locator = element_locator_factory.call(@page_element, *args)
|
36
36
|
end
|
37
37
|
|
38
|
-
result = element_locator.
|
38
|
+
result = element_locator.browser_element
|
39
39
|
|
40
|
-
return element_locator if element_locator.
|
40
|
+
return element_locator if element_locator.section? && action.nil?
|
41
41
|
|
42
42
|
[:set, :select_option, :unselect_option, :click].each do |action_method|
|
43
43
|
apply_hooks(page_element: result,
|
44
44
|
capybara_method: action_method,
|
45
|
-
before_hook: element_locator.
|
46
|
-
after_hook: element_locator.
|
45
|
+
before_hook: element_locator.before,
|
46
|
+
after_hook: element_locator.after,
|
47
47
|
)
|
48
48
|
end
|
49
49
|
|
data/lib/page_magic/elements.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ext/string'
|
1
2
|
module PageMagic
|
2
3
|
module Elements
|
3
4
|
class InvalidElementNameException < Exception
|
@@ -24,67 +25,45 @@ module PageMagic
|
|
24
25
|
raise InvalidMethodNameException, "method name matches element name" if element_definitions[method]
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
28
|
def elements(browser_element, *args)
|
29
29
|
element_definitions.values.collect { |definition| definition.call(browser_element, *args) }
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
TYPES = [:element, :text_field, :button, :link, :checkbox, :select_list, :radios, :textarea, :section]
|
33
|
+
TYPES.each do |type|
|
34
|
+
define_method type do |*args, &block|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
define_method field do |*args, &block|
|
39
|
-
name, selector = args
|
40
|
-
add_element_definition(name) do |browser_element|
|
41
|
-
case selector
|
42
|
-
when Hash, NilClass
|
43
|
-
Element.new(name, browser_element, field, selector, &block)
|
44
|
-
else
|
45
|
-
Element.new(name, selector, field, nil, &block)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def section *args, &block
|
53
|
-
case args.first
|
54
|
-
when Symbol
|
36
|
+
first_arg = args.first
|
37
|
+
if first_arg.is_a?(Symbol)
|
55
38
|
name, selector = args
|
56
39
|
|
57
|
-
add_element_definition(name) do |
|
58
|
-
page_section =
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
page_section.parent_browser_element = parent_browser_element.browser_element
|
40
|
+
add_element_definition(name) do |*args_for_block|
|
41
|
+
page_section = PageMagic::Element.new name, args_for_block.delete_at(0), type, selector
|
42
|
+
page_section.instance_exec *args_for_block, &(block || Proc.new {})
|
43
|
+
page_section
|
44
|
+
end
|
63
45
|
|
64
|
-
|
65
|
-
|
66
|
-
page_section.selector selector
|
67
|
-
else
|
68
|
-
page_section.browser_element = selector
|
69
|
-
end
|
46
|
+
elsif first_arg < PageMagic::Element
|
47
|
+
section_class, name, selector = args
|
70
48
|
|
71
|
-
|
72
|
-
|
73
|
-
|
49
|
+
unless selector
|
50
|
+
selector = name
|
51
|
+
name = section_class.name.to_snake_case
|
74
52
|
end
|
75
|
-
|
76
|
-
section_class, name, selector = args
|
53
|
+
|
77
54
|
add_element_definition(name) do |parent_browser_element|
|
78
|
-
section_class.new(parent_browser_element,
|
55
|
+
section_class.new(name, parent_browser_element, :section, selector)
|
79
56
|
end
|
80
|
-
end
|
81
|
-
|
82
57
|
|
58
|
+
end
|
59
|
+
end
|
83
60
|
end
|
84
61
|
|
85
62
|
def add_element_definition name, &block
|
86
63
|
raise InvalidElementNameException, "duplicate page element defined" if element_definitions[name]
|
87
|
-
|
64
|
+
|
65
|
+
methods = respond_to?(:instance_methods) ? instance_methods : methods()
|
66
|
+
raise InvalidElementNameException, "a method already exists with this method name" if methods.find { |method| method == name }
|
88
67
|
|
89
68
|
element_definitions[name] = block
|
90
69
|
end
|
@@ -3,13 +3,11 @@ module PageMagic
|
|
3
3
|
|
4
4
|
include AjaxSupport
|
5
5
|
|
6
|
-
def initialize session=Capybara.current_session, options={}, &block
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@session = session
|
12
|
-
end
|
6
|
+
def initialize session=Session.new(Capybara.current_session), options={}, &block
|
7
|
+
|
8
|
+
@browser = session.raw_session
|
9
|
+
@session = session
|
10
|
+
|
13
11
|
@browser_element = @browser
|
14
12
|
navigate if options[:navigate_to_page]
|
15
13
|
block.call @browser if block
|
@@ -23,39 +21,15 @@ module PageMagic
|
|
23
21
|
@browser.refresh
|
24
22
|
end
|
25
23
|
|
26
|
-
def current_path
|
27
|
-
@browser.current_path
|
28
|
-
end
|
29
|
-
|
30
24
|
def text_on_page? text
|
31
25
|
text().downcase.include?(text.downcase)
|
32
26
|
end
|
33
27
|
|
34
|
-
def window_exists? title
|
35
|
-
raise "implement me"
|
36
|
-
end
|
37
|
-
|
38
|
-
def accept_popup
|
39
|
-
raise "implement me"
|
40
|
-
end
|
41
|
-
|
42
|
-
def alert_present?
|
43
|
-
raise "implement me"
|
44
|
-
end
|
45
|
-
|
46
|
-
def text_in_popup? text
|
47
|
-
raise "implement me"
|
48
|
-
end
|
49
|
-
|
50
28
|
def visit
|
51
29
|
@browser.visit self.class.url
|
52
30
|
self
|
53
31
|
end
|
54
32
|
|
55
|
-
def click element
|
56
|
-
self.send(element.downcase.gsub(" ", "_").to_sym)
|
57
|
-
end
|
58
|
-
|
59
33
|
def text
|
60
34
|
@browser.text
|
61
35
|
end
|
data/lib/page_magic/session.rb
CHANGED
@@ -1,27 +1,30 @@
|
|
1
1
|
require 'wait'
|
2
2
|
module PageMagic
|
3
3
|
class Session
|
4
|
-
|
5
|
-
attr_accessor :current_page
|
4
|
+
attr_accessor :current_page, :raw_session
|
6
5
|
|
7
6
|
def initialize browser
|
8
|
-
@
|
7
|
+
@raw_session = browser
|
9
8
|
end
|
10
9
|
|
11
10
|
def visit page
|
12
|
-
@
|
11
|
+
@raw_session.visit page.url
|
13
12
|
@current_page = page.new self
|
14
13
|
self
|
15
14
|
end
|
16
15
|
|
16
|
+
def current_path
|
17
|
+
@raw_session.current_path
|
18
|
+
end
|
19
|
+
|
17
20
|
def current_url
|
18
|
-
@
|
21
|
+
@raw_session.current_url
|
19
22
|
end
|
20
23
|
|
21
24
|
def move_to page_class
|
22
25
|
page_class = eval(page_class) if page_class.is_a?(String)
|
23
26
|
@current_page = page_class.new self
|
24
|
-
wait_until {
|
27
|
+
wait_until { raw_session.current_url == page_class.url }
|
25
28
|
end
|
26
29
|
|
27
30
|
def wait_until &block
|
@@ -32,5 +35,6 @@ module PageMagic
|
|
32
35
|
def method_missing name, *args, &block
|
33
36
|
@current_page.send(name, *args, &block)
|
34
37
|
end
|
38
|
+
|
35
39
|
end
|
36
40
|
end
|
data/lib/page_magic.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}")
|
2
2
|
require 'capybara'
|
3
|
+
require 'page_magic/exceptions'
|
3
4
|
require 'page_magic/browser'
|
4
5
|
require 'page_magic/session'
|
5
6
|
require 'page_magic/ajax_support'
|
@@ -7,7 +8,6 @@ require 'page_magic/elements'
|
|
7
8
|
require 'page_magic/element_context'
|
8
9
|
require 'page_magic/element'
|
9
10
|
require 'page_magic/page_magic'
|
10
|
-
require 'page_magic/section'
|
11
11
|
|
12
12
|
module PageMagic
|
13
13
|
class << self
|
data/page_magic.gemspec
CHANGED
@@ -5,17 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "page_magic"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.11.0.alpha"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Leon Davis"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2014-03-05"
|
13
13
|
s.description = "Framework for modeling and interacting with webpages which wraps capybara"
|
14
14
|
s.email = "info@lad-tech.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README.md"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
+
".rspec",
|
19
20
|
".ruby-gemset",
|
20
21
|
".ruby-version",
|
21
22
|
".travis.yml",
|
@@ -24,24 +25,28 @@ Gem::Specification.new do |s|
|
|
24
25
|
"README.md",
|
25
26
|
"Rakefile",
|
26
27
|
"VERSION",
|
28
|
+
"lib/ext/string.rb",
|
27
29
|
"lib/page_magic.rb",
|
28
30
|
"lib/page_magic/ajax_support.rb",
|
29
31
|
"lib/page_magic/browser.rb",
|
30
32
|
"lib/page_magic/element.rb",
|
31
33
|
"lib/page_magic/element_context.rb",
|
32
34
|
"lib/page_magic/elements.rb",
|
35
|
+
"lib/page_magic/exceptions.rb",
|
33
36
|
"lib/page_magic/page_magic.rb",
|
34
|
-
"lib/page_magic/section.rb",
|
35
37
|
"lib/page_magic/session.rb",
|
36
38
|
"page_magic.gemspec",
|
37
39
|
"spec/browser_spec.rb",
|
38
40
|
"spec/element_context_spec.rb",
|
39
41
|
"spec/element_spec.rb",
|
40
|
-
"spec/elements_spec.rb",
|
41
42
|
"spec/helpers/capybara.rb",
|
42
43
|
"spec/member_methods_spec.rb",
|
43
|
-
"spec/
|
44
|
-
"spec/
|
44
|
+
"spec/page_magic/elements/elements_spec.rb",
|
45
|
+
"spec/page_magic/usage/defining_page_elements_spec.rb",
|
46
|
+
"spec/page_magic/usage/defining_pages_spec.rb",
|
47
|
+
"spec/page_magic/usage/include_page_magic_spec.rb",
|
48
|
+
"spec/page_magic/usage/interacting_with_pages_spec.rb",
|
49
|
+
"spec/page_magic/usage/starting_a_session_spec.rb",
|
45
50
|
"spec/session_spec.rb",
|
46
51
|
"spec/spec_helper.rb"
|
47
52
|
]
|
@@ -22,7 +22,7 @@ describe 'Element Context' do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
let!(:session) do
|
25
|
-
double('session',
|
25
|
+
double('session', raw_session: double('browser'))
|
26
26
|
end
|
27
27
|
|
28
28
|
describe 'resolving field definitions' do
|
@@ -70,7 +70,7 @@ describe 'Element Context' do
|
|
70
70
|
page.visit
|
71
71
|
|
72
72
|
PageMagic::ElementContext.new(page, page.browser, self).click_next
|
73
|
-
page.current_path.should == '/page2'
|
73
|
+
page.session.current_path.should == '/page2'
|
74
74
|
page.text.should == 'page 2 content'
|
75
75
|
end
|
76
76
|
end
|
@@ -82,16 +82,38 @@ describe 'Element Context' do
|
|
82
82
|
elements_page.class_eval do
|
83
83
|
section :form do
|
84
84
|
selector css: '.form'
|
85
|
+
link :form_link, text: 'in a form'
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
88
89
|
page = elements_page.new
|
89
90
|
page.visit
|
90
91
|
|
91
|
-
PageMagic::ElementContext.new(page, page.browser, self).form
|
92
|
+
PageMagic::ElementContext.new(page, page.browser, self).form
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'they are clickable too' do
|
96
|
+
elements_page.class_eval do
|
97
|
+
section :section do
|
98
|
+
selector id: 'form_link'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
page = elements_page.new
|
103
|
+
page.visit
|
104
|
+
|
105
|
+
|
106
|
+
PageMagic::ElementContext.new(page, page.browser, self).click_section
|
107
|
+
page.session.current_path.should == '/page2'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should delegate to page element if method not found' do
|
111
|
+
#TODO call page method, look for subelement, delagate to capybara object
|
92
112
|
end
|
93
113
|
end
|
94
114
|
|
115
|
+
|
116
|
+
|
95
117
|
describe 'hooks' do
|
96
118
|
|
97
119
|
it 'should execute a before and after action that gives access to the browser' do
|