page_magic 0.10.0 → 0.11.0.alpha

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/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require 'spec_helper'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.0
1
+ 0.11.0.alpha
data/lib/ext/string.rb ADDED
@@ -0,0 +1,9 @@
1
+ class String
2
+ def to_snake_case
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end
@@ -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
- class MissingLocatorOrSelector < Exception
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
- @parent_page_element = parent_page_element
29
- if selector
30
- @browser_element = parent_page_element.browser_element
9
+ if selector.is_a?(Hash)
10
+ @selector = selector
31
11
  else
32
- @browser_element = parent_page_element
12
+ @browser_element = selector
33
13
  end
34
14
 
35
- @type = type
36
- @name = name.downcase.to_sym
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
- @before_hook, @after_hook = self.class.default_before_hook, self.class.default_after_hook
40
- instance_eval &block if block_given?
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 locate *args
56
- if @selector && @selector.is_a?(Hash)
57
- method, selector = @selector.to_a.flatten
58
- case method
59
- when :id
60
- @browser_element.find("##{selector}")
61
- when :name
62
- @browser_element.find("*[name='#{selector}']")
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
- def == page_element
86
- page_element.is_a?(Element) &&
87
- @type == page_element.type &&
88
- @name == page_element.name &&
89
- @selector == page_element.selector
90
- @before_hook == page_element.before_hook &&
91
- @after_hook == page_element.after_hook
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.locate
38
+ result = element_locator.browser_element
39
39
 
40
- return element_locator if element_locator.class.is_a? Section
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.before_hook,
46
- after_hook: element_locator.after_hook,
45
+ before_hook: element_locator.before,
46
+ after_hook: element_locator.after,
47
47
  )
48
48
  end
49
49
 
@@ -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
- def elements?
33
- !element_definitions.empty?
34
- end
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
- TYPES = [:element, :text_field, :button, :link, :checkbox, :select_list, :radios, :textarea]
37
- TYPES.each do |field|
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 |parent_browser_element, *args_for_section|
58
- page_section = Class.new do
59
- extend PageMagic::Section
60
- end
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
- case selector
65
- when Hash
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
- block = block || Proc.new{}
72
- page_section.class_exec *args_for_section, &block
73
- page_section.new(parent_browser_element, name, selector)
49
+ unless selector
50
+ selector = name
51
+ name = section_class.name.to_snake_case
74
52
  end
75
- else
76
- section_class, name, selector = args
53
+
77
54
  add_element_definition(name) do |parent_browser_element|
78
- section_class.new(parent_browser_element, name, selector)
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
- raise InvalidElementNameException, "a method already exists with this method name" if instance_methods.find { |method| method == name }
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
@@ -0,0 +1,10 @@
1
+ module PageMagic
2
+ class UnsupportedSelectorException < Exception
3
+
4
+ end
5
+ class UndefinedSelectorException < Exception
6
+ end
7
+
8
+ class MissingLocatorOrSelector < Exception
9
+ end
10
+ 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
- if session.is_a? Capybara::Session
8
- @browser = session
9
- else
10
- @browser = session.browser
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
@@ -1,27 +1,30 @@
1
1
  require 'wait'
2
2
  module PageMagic
3
3
  class Session
4
- attr_reader :browser
5
- attr_accessor :current_page
4
+ attr_accessor :current_page, :raw_session
6
5
 
7
6
  def initialize browser
8
- @browser = browser
7
+ @raw_session = browser
9
8
  end
10
9
 
11
10
  def visit page
12
- @browser.visit page.url
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
- @browser.current_url
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 { browser.current_url == page_class.url }
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.10.0"
8
+ s.version = "0.11.0.alpha"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
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 = "2013-12-16"
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/page_magic_spec.rb",
44
- "spec/section_spec.rb",
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', browser: double('browser'))
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('a', 'b')
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