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 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