page_magic 0.8.8
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/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +74 -0
- data/README.md +1 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/lib/page_magic/ajax_support.rb +21 -0
- data/lib/page_magic/browser.rb +16 -0
- data/lib/page_magic/element_context.rb +81 -0
- data/lib/page_magic/page_element.rb +99 -0
- data/lib/page_magic/page_elements.rb +91 -0
- data/lib/page_magic/page_magic.rb +70 -0
- data/lib/page_magic/page_section.rb +101 -0
- data/lib/page_magic/session.rb +28 -0
- data/lib/page_magic/wait.rb +7 -0
- data/lib/page_magic.rb +55 -0
- data/page_magic.gemspec +80 -0
- data/spec/browser_spec.rb +33 -0
- data/spec/element_context_spec.rb +123 -0
- data/spec/helpers/capybara.rb +10 -0
- data/spec/helpers.rb +1 -0
- data/spec/member_methods_spec.rb +36 -0
- data/spec/page_element_spec.rb +80 -0
- data/spec/page_elements_spec.rb +202 -0
- data/spec/page_magic_spec.rb +143 -0
- data/spec/page_section_spec.rb +101 -0
- data/spec/session_spec.rb +64 -0
- data/spec/spec_helper.rb +45 -0
- metadata +159 -0
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
page_magic
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "watir-webdriver"
|
4
|
+
gem 'capybara'
|
5
|
+
gem 'wait'
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem 'sinatra'
|
9
|
+
gem "rspec", require: 'rspec/core/rake_task'
|
10
|
+
gem "simplecov", require: false
|
11
|
+
end
|
12
|
+
|
13
|
+
group :development do
|
14
|
+
gem "jeweler", "~> 1.8.4"
|
15
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
capybara (2.1.0)
|
5
|
+
mime-types (>= 1.16)
|
6
|
+
nokogiri (>= 1.3.3)
|
7
|
+
rack (>= 1.0.0)
|
8
|
+
rack-test (>= 0.5.4)
|
9
|
+
xpath (~> 2.0)
|
10
|
+
childprocess (0.3.9)
|
11
|
+
ffi (~> 1.0, >= 1.0.11)
|
12
|
+
diff-lcs (1.2.4)
|
13
|
+
ffi (1.8.1)
|
14
|
+
git (1.2.5)
|
15
|
+
jeweler (1.8.4)
|
16
|
+
bundler (~> 1.0)
|
17
|
+
git (>= 1.2.5)
|
18
|
+
rake
|
19
|
+
rdoc
|
20
|
+
json (1.7.7)
|
21
|
+
mime-types (1.25)
|
22
|
+
mini_portile (0.5.1)
|
23
|
+
multi_json (1.7.3)
|
24
|
+
nokogiri (1.6.0)
|
25
|
+
mini_portile (~> 0.5.0)
|
26
|
+
rack (1.5.2)
|
27
|
+
rack-protection (1.5.0)
|
28
|
+
rack
|
29
|
+
rack-test (0.6.2)
|
30
|
+
rack (>= 1.0)
|
31
|
+
rake (10.0.4)
|
32
|
+
rdoc (4.0.1)
|
33
|
+
json (~> 1.4)
|
34
|
+
rspec (2.14.1)
|
35
|
+
rspec-core (~> 2.14.0)
|
36
|
+
rspec-expectations (~> 2.14.0)
|
37
|
+
rspec-mocks (~> 2.14.0)
|
38
|
+
rspec-core (2.14.6)
|
39
|
+
rspec-expectations (2.14.3)
|
40
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
41
|
+
rspec-mocks (2.14.4)
|
42
|
+
rubyzip (0.9.9)
|
43
|
+
selenium-webdriver (2.32.1)
|
44
|
+
childprocess (>= 0.2.5)
|
45
|
+
multi_json (~> 1.0)
|
46
|
+
rubyzip
|
47
|
+
websocket (~> 1.0.4)
|
48
|
+
simplecov (0.7.1)
|
49
|
+
multi_json (~> 1.0)
|
50
|
+
simplecov-html (~> 0.7.1)
|
51
|
+
simplecov-html (0.7.1)
|
52
|
+
sinatra (1.4.3)
|
53
|
+
rack (~> 1.4)
|
54
|
+
rack-protection (~> 1.4)
|
55
|
+
tilt (~> 1.3, >= 1.3.4)
|
56
|
+
tilt (1.4.1)
|
57
|
+
wait (0.5.1)
|
58
|
+
watir-webdriver (0.6.4)
|
59
|
+
selenium-webdriver (>= 2.18.0)
|
60
|
+
websocket (1.0.7)
|
61
|
+
xpath (2.0.0)
|
62
|
+
nokogiri (~> 1.3)
|
63
|
+
|
64
|
+
PLATFORMS
|
65
|
+
ruby
|
66
|
+
|
67
|
+
DEPENDENCIES
|
68
|
+
capybara
|
69
|
+
jeweler (~> 1.8.4)
|
70
|
+
rspec
|
71
|
+
simplecov
|
72
|
+
sinatra
|
73
|
+
wait
|
74
|
+
watir-webdriver
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
[](https://travis-ci.org/Ladtech/page_magic)
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Bundler.require :test,:development
|
2
|
+
|
3
|
+
RSpec::Core::RakeTask.new(:spec) do
|
4
|
+
ENV['coverage'] = "true"
|
5
|
+
end
|
6
|
+
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "page_magic"
|
9
|
+
gem.homepage = "https://github.com/ladtech/page_magic"
|
10
|
+
gem.license = "ruby"
|
11
|
+
gem.summary = "Framework for modeling and interacting with webpages"
|
12
|
+
gem.description = "Framework for modeling and interacting with webpages which wraps capybara"
|
13
|
+
gem.email = "info@lad-tech.com"
|
14
|
+
gem.authors = ["Leon Davis"]
|
15
|
+
gem.add_dependency "watir-webdriver"
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::RubygemsDotOrgTasks.new
|
19
|
+
|
20
|
+
task :default => :spec
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.8.8
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PageMagic
|
2
|
+
module AjaxSupport
|
3
|
+
def on_element_with_trigger css_selector, event, browser, &block
|
4
|
+
set_variable_on_event(browser, css_selector, event)
|
5
|
+
yield
|
6
|
+
wait_until(:timeout_after => 20.seconds, :retry_every => 1.second) do
|
7
|
+
event_triggered(browser, event)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def event_triggered(browser, variable)
|
12
|
+
browser.execute_script("return #{variable}_triggered")
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_variable_on_event(browser, element, event)
|
16
|
+
variable_name="#{event}_triggered"
|
17
|
+
browser.execute_script("#{variable_name}=false")
|
18
|
+
browser.execute_script("$('#{element}').on('#{event}', function(){#{variable_name}=true})")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PageMagic
|
2
|
+
module Browser
|
3
|
+
class << self
|
4
|
+
attr_reader :browser
|
5
|
+
attr_accessor :session
|
6
|
+
|
7
|
+
def use browser
|
8
|
+
@browser = browser
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def browser
|
13
|
+
Browser.session ||= PageMagic.session(Browser.browser || :chrome)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module PageMagic
|
2
|
+
|
3
|
+
class ElementMissingException < Exception
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
class ElementContext
|
8
|
+
|
9
|
+
attr_reader :caller, :page_element
|
10
|
+
|
11
|
+
def initialize page_element, browser, caller, *args
|
12
|
+
@page_element = page_element
|
13
|
+
@browser = browser
|
14
|
+
@caller = caller
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing method, *args
|
18
|
+
return @caller.send(method, *args) if @executing_hooks
|
19
|
+
return @page_element.send(method, *args) if @page_element.methods.include?(method)
|
20
|
+
|
21
|
+
|
22
|
+
element_locator_factory = @page_element.element_definitions[method]
|
23
|
+
|
24
|
+
action = nil
|
25
|
+
unless element_locator_factory
|
26
|
+
action = resolve_action(method)
|
27
|
+
element_locator_factory = @page_element.element_definitions[method.to_s.gsub("#{action}_", '').to_sym]
|
28
|
+
end
|
29
|
+
|
30
|
+
raise ElementMissingException, "Could not find: #{method}" unless element_locator_factory
|
31
|
+
|
32
|
+
if args.empty?
|
33
|
+
element_locator = element_locator_factory.call(@page_element, nil)
|
34
|
+
else
|
35
|
+
element_locator = element_locator_factory.call(@page_element, *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
result = element_locator.locate
|
39
|
+
|
40
|
+
return element_locator if element_locator.class.is_a? PageSection
|
41
|
+
|
42
|
+
[:set, :select_option, :unselect_option, :click].each do |action_method|
|
43
|
+
apply_hooks(page_element: result,
|
44
|
+
capybara_method: action_method,
|
45
|
+
before_hook: element_locator.before_hook,
|
46
|
+
after_hook: element_locator.after_hook,
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
action ? result.send(action) : result
|
51
|
+
end
|
52
|
+
|
53
|
+
def resolve_action(field)
|
54
|
+
{/^click_/ => :click}.each do |prefix, action|
|
55
|
+
return action if field.to_s =~ prefix
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def apply_hooks(options)
|
60
|
+
_self = self
|
61
|
+
page_element, capybara_method = options[:page_element], options[:capybara_method]
|
62
|
+
|
63
|
+
original_method = page_element.method(capybara_method)
|
64
|
+
|
65
|
+
page_element.define_singleton_method capybara_method do |*arguments, &block|
|
66
|
+
_self.call_hook &options[:before_hook]
|
67
|
+
original_method.call *arguments, &block
|
68
|
+
_self.call_hook &options[:after_hook]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def call_hook &block
|
74
|
+
@executing_hooks = true
|
75
|
+
result = self.instance_exec @browser, &block
|
76
|
+
@executing_hooks = false
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'watir-webdriver'
|
2
|
+
module PageMagic
|
3
|
+
|
4
|
+
class UnsupportedSelectorException < Exception
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
class PageElement
|
9
|
+
|
10
|
+
class MissingLocatorOrSelector < Exception
|
11
|
+
end
|
12
|
+
|
13
|
+
include PageElements
|
14
|
+
include AjaxSupport
|
15
|
+
|
16
|
+
module ::Watir
|
17
|
+
SelectList = Select
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :type, :name, :selector, :before_hook, :after_hook, :browser_element, :locator
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def default_before_hook
|
24
|
+
@default_before_hook ||= Proc.new {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_after_hook
|
28
|
+
@default_after_hook ||= Proc.new {}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize name, parent_page_element, type=nil, selector=nil, &block
|
33
|
+
@parent_page_element = parent_page_element
|
34
|
+
if selector
|
35
|
+
@browser_element = parent_page_element.browser_element
|
36
|
+
else
|
37
|
+
@browser_element = parent_page_element
|
38
|
+
end
|
39
|
+
|
40
|
+
@type = type
|
41
|
+
@name = name.downcase.to_sym
|
42
|
+
@selector = selector
|
43
|
+
|
44
|
+
@before_hook, @after_hook = self.class.default_before_hook, self.class.default_after_hook
|
45
|
+
instance_eval &block if block_given?
|
46
|
+
end
|
47
|
+
|
48
|
+
def session
|
49
|
+
@parent_page_element.session
|
50
|
+
end
|
51
|
+
|
52
|
+
def before &block
|
53
|
+
@before_hook = block
|
54
|
+
end
|
55
|
+
|
56
|
+
def after &block
|
57
|
+
@after_hook = block
|
58
|
+
end
|
59
|
+
|
60
|
+
def locate *args
|
61
|
+
if @selector && @selector.is_a?(Hash)
|
62
|
+
method, selector = @selector.to_a.flatten
|
63
|
+
case method
|
64
|
+
when :id
|
65
|
+
@browser_element.find("##{selector}")
|
66
|
+
when :name
|
67
|
+
@browser_element.find("*[name='#{selector}']")
|
68
|
+
when :label
|
69
|
+
@browser_element.find_field(selector)
|
70
|
+
when :text
|
71
|
+
if @type == :link
|
72
|
+
@browser_element.find_link(selector)
|
73
|
+
elsif @type == :button
|
74
|
+
@browser_element.find_button(selector)
|
75
|
+
else
|
76
|
+
raise UnsupportedSelectorException
|
77
|
+
end
|
78
|
+
when :css
|
79
|
+
@browser_element.find(:css, selector)
|
80
|
+
else
|
81
|
+
raise UnsupportedSelectorException
|
82
|
+
|
83
|
+
end
|
84
|
+
else
|
85
|
+
@browser_element
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def == page_element
|
91
|
+
page_element.is_a?(PageElement) &&
|
92
|
+
@type == page_element.type &&
|
93
|
+
@name == page_element.name &&
|
94
|
+
@selector == page_element.selector
|
95
|
+
@before_hook == page_element.before_hook &&
|
96
|
+
@after_hook == page_element.after_hook
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module PageMagic
|
2
|
+
module PageElements
|
3
|
+
class InvalidElementNameException < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
class InvalidMethodNameException < Exception
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.extended clazz
|
10
|
+
clazz.class_eval do
|
11
|
+
attr_reader :browser_element
|
12
|
+
|
13
|
+
def elements browser_element, *args
|
14
|
+
self.class.elements browser_element, *args
|
15
|
+
end
|
16
|
+
|
17
|
+
def element_definitions
|
18
|
+
self.class.element_definitions
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_added method
|
25
|
+
raise InvalidMethodNameException, "method name matches element name" if element_definitions[method]
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def elements(browser_element, *args)
|
31
|
+
element_definitions.values.collect { |definition| definition.call(browser_element, *args) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def elements?
|
35
|
+
!element_definitions.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
ELEMENT_TYPES = [:element, :text_field, :button, :link, :checkbox, :select_list, :radios, :textarea]
|
39
|
+
ELEMENT_TYPES.each do |field|
|
40
|
+
define_method field do |*args, &block|
|
41
|
+
name, selector = args
|
42
|
+
add_element_definition(name) do |browser_element|
|
43
|
+
case selector
|
44
|
+
when Hash, NilClass
|
45
|
+
PageElement.new(name, browser_element, field, selector, &block)
|
46
|
+
else
|
47
|
+
PageElement.new(name, selector, field, nil, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def section *args, &block
|
55
|
+
case args.first
|
56
|
+
when Symbol
|
57
|
+
name, selector = args
|
58
|
+
|
59
|
+
add_element_definition(name) do |parent_browser_element, *args_for_section|
|
60
|
+
page_section = Class.new do
|
61
|
+
extend PageMagic::PageSection
|
62
|
+
end
|
63
|
+
|
64
|
+
page_section.parent_browser_element = parent_browser_element.browser_element
|
65
|
+
page_section.selector selector if selector
|
66
|
+
|
67
|
+
page_section.class_exec *args_for_section, &block
|
68
|
+
page_section.new(parent_browser_element, name, selector)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
section_class, name, selector = args
|
72
|
+
add_element_definition(name) do |parent_browser_element|
|
73
|
+
section_class.new(parent_browser_element, name, selector)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_element_definition name, &block
|
81
|
+
raise InvalidElementNameException, "duplicate page element defined" if element_definitions[name]
|
82
|
+
raise InvalidElementNameException, "a method already exists with this method name" if instance_methods.find { |method| method == name }
|
83
|
+
|
84
|
+
element_definitions[name] = block
|
85
|
+
end
|
86
|
+
|
87
|
+
def element_definitions
|
88
|
+
@element_definitions ||= {}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module PageMagic
|
2
|
+
attr_reader :browser, :session
|
3
|
+
|
4
|
+
include AjaxSupport
|
5
|
+
|
6
|
+
def initialize session=Capybara.current_session, options={}, &block
|
7
|
+
if session.is_a? Capybara::Session
|
8
|
+
@browser = session
|
9
|
+
else
|
10
|
+
@browser = session.browser
|
11
|
+
@session = session
|
12
|
+
end
|
13
|
+
@browser_element = @browser
|
14
|
+
navigate if options[:navigate_to_page]
|
15
|
+
block.call @browser if block
|
16
|
+
end
|
17
|
+
|
18
|
+
def title
|
19
|
+
@browser.title
|
20
|
+
end
|
21
|
+
|
22
|
+
def refresh
|
23
|
+
@browser.refresh
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_path
|
27
|
+
@browser.current_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def text_on_page? text
|
31
|
+
text().downcase.include?(text.downcase)
|
32
|
+
end
|
33
|
+
|
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
|
+
def visit
|
51
|
+
@browser.visit self.class.url
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def click element
|
56
|
+
self.send(element.downcase.gsub(" ", "_").to_sym)
|
57
|
+
end
|
58
|
+
|
59
|
+
def text
|
60
|
+
@browser.text
|
61
|
+
end
|
62
|
+
|
63
|
+
def method_missing method, *args
|
64
|
+
ElementContext.new(self, @browser, self).send(method, *args)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module PageMagic
|
2
|
+
module PageSection
|
3
|
+
|
4
|
+
module Location
|
5
|
+
def locate_in browser_element, selector
|
6
|
+
method, selector = selector.to_a.flatten
|
7
|
+
case method
|
8
|
+
when :id
|
9
|
+
browser_element.find("##{selector}")
|
10
|
+
when :css
|
11
|
+
browser_element.find(:css, selector)
|
12
|
+
else
|
13
|
+
raise UnsupportedSelectorException
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class UndefinedSelectorException < Exception
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def extended clazz
|
23
|
+
clazz.extend(PageElements)
|
24
|
+
clazz.class_eval do
|
25
|
+
attr_reader :name, :selector
|
26
|
+
class << self
|
27
|
+
def selector selector=nil
|
28
|
+
return @selector unless selector
|
29
|
+
|
30
|
+
if @parent_browser_element
|
31
|
+
@browser_element = locate_in @parent_browser_element, selector
|
32
|
+
end
|
33
|
+
|
34
|
+
@selector = selector
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :parent_browser_element, :browser_element
|
38
|
+
end
|
39
|
+
|
40
|
+
include Location
|
41
|
+
extend Location
|
42
|
+
|
43
|
+
def initialize parent_page_element, name=nil, selector=self.class.selector
|
44
|
+
|
45
|
+
@selector = selector
|
46
|
+
@parent_page_element = parent_page_element
|
47
|
+
|
48
|
+
@selector = selector ? selector : self.class.selector
|
49
|
+
|
50
|
+
raise UndefinedSelectorException, "Pass a selector to the constructor/define one the class" unless @selector
|
51
|
+
@browser_element = locate_in(@parent_page_element.browser_element, @selector)
|
52
|
+
if name
|
53
|
+
@name = name
|
54
|
+
else
|
55
|
+
@name = underscore(self.class.name).to_sym
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def session
|
62
|
+
@parent_page_element.session
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO test this
|
66
|
+
def locate *args
|
67
|
+
@browser_element
|
68
|
+
end
|
69
|
+
|
70
|
+
#TODO - consolidate this
|
71
|
+
def method_missing method, *args
|
72
|
+
begin
|
73
|
+
ElementContext.new(self, @browser_element, self, *args).send(method, args.first)
|
74
|
+
rescue ElementMissingException
|
75
|
+
begin
|
76
|
+
@browser_element.send(method, *args)
|
77
|
+
rescue
|
78
|
+
super
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def underscore string
|
87
|
+
string.gsub(/::/, '/').
|
88
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
89
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
90
|
+
tr("-", "_").
|
91
|
+
downcase
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PageMagic
|
2
|
+
class Session
|
3
|
+
attr_reader :browser
|
4
|
+
attr_accessor :current_page
|
5
|
+
|
6
|
+
include WaitUntil
|
7
|
+
|
8
|
+
def initialize browser
|
9
|
+
@browser = browser
|
10
|
+
end
|
11
|
+
|
12
|
+
def visit page
|
13
|
+
@browser.visit page.url
|
14
|
+
@current_page = page.new self
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def move_to page_class
|
19
|
+
page_class = eval(page_class) if page_class.is_a?(String)
|
20
|
+
@current_page = page_class.new self
|
21
|
+
wait.until { browser.current_url == page_class.url }
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing name, *args, &block
|
25
|
+
@current_page.send(name, *args, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|