page_magic 1.0.0.alpha18 → 1.0.0.alpha19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57c321555c03ce3b8a6a43d895ffd657eca3c5ae
4
- data.tar.gz: f656f163ed661b0b48ffbc5b2b2d30f5db777beb
3
+ metadata.gz: 3c6619b6e1c9d8dfc99efdf0c0e7ebe74a47d982
4
+ data.tar.gz: 1cf1b031cd205134d43abd54d73026f9d41ad864
5
5
  SHA512:
6
- metadata.gz: 4cd81bb246ed5a267265db1ab31d8861a772c9fa54ac000e0d5dd4ac9340a180a0c047876fe28bd2cbf3a58e29840b342f221c15f1f13564f6486dcc0b1e2806
7
- data.tar.gz: 8957aa92ef4ae0dc088fed4d4bf7d13feae4118064b12270add171fe52f0fda423fa8787fcef5b1112b526171bc308676bdc2d9f40c79502da928250b1c8a3a1
6
+ metadata.gz: be32d07b0103409b817333a632091d1b5b88f3173c1562c39df3dfa2e3d98f26a8e36a95d6ef2f878a7d4240c192d2165452a18d77ac52b0b0c6d27f2bd8451a
7
+ data.tar.gz: db76720173bdcb1d0fb43fe1721386d0c36e32c76fd354fabde19798cbddc1ba59b376a32942073a6aeb92ee1c3cfd4f948c8711d0ddff63e994d9e6572c5f78
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'capybara'
4
- gem 'activesupport'
5
- gem 'wait'
3
+ gem 'capybara', '~> 2'
4
+ gem 'activesupport', '~> 4'
5
+ gem 'wait', '~> 0'
6
6
 
7
7
  group :test do
8
8
  gem 'watir-webdriver'
@@ -15,10 +15,9 @@ group :test do
15
15
  end
16
16
 
17
17
  group :development do
18
- gem 'jeweler'
19
- gem 'rubocop', require: 'rubocop/rake_task'
20
- gem 'pry-byebug'
21
- gem 'yard'
22
- gem 'redcarpet'
23
- gem 'github-markup'
18
+ gem 'jeweler', '~> 2.0'
19
+ gem 'rubocop', '~> 0.34', require: 'rubocop/rake_task'
20
+ gem 'yard', '~> 0.8'
21
+ gem 'redcarpet', '~> 3.3'
22
+ gem 'github-markup', '~> 1.4'
24
23
  end
data/Gemfile.lock CHANGED
@@ -12,8 +12,6 @@ GEM
12
12
  astrolabe (1.3.1)
13
13
  parser (~> 2.2)
14
14
  builder (3.2.2)
15
- byebug (5.0.0)
16
- columnize (= 0.9.0)
17
15
  capybara (2.1.0)
18
16
  mime-types (>= 1.16)
19
17
  nokogiri (>= 1.3.3)
@@ -26,8 +24,6 @@ GEM
26
24
  cliver (0.2.2)
27
25
  codeclimate-test-reporter (0.4.8)
28
26
  simplecov (>= 0.7.1, < 1.0.0)
29
- coderay (1.1.0)
30
- columnize (0.9.0)
31
27
  diff-lcs (1.2.5)
32
28
  docile (1.1.5)
33
29
  faraday (0.8.9)
@@ -57,22 +53,21 @@ GEM
57
53
  json (1.8.1)
58
54
  jwt (0.1.11)
59
55
  multi_json (>= 1.5)
60
- method_source (0.8.2)
61
- mime-types (1.25)
62
- mini_portile (0.5.1)
56
+ mime-types (2.6.2)
57
+ mini_portile (0.6.2)
63
58
  minitest (5.7.0)
64
59
  multi_json (1.11.2)
65
60
  multi_xml (0.5.5)
66
61
  multipart-post (1.2.0)
67
- nokogiri (1.6.0)
68
- mini_portile (~> 0.5.0)
62
+ nokogiri (1.6.6.2)
63
+ mini_portile (~> 0.6.0)
69
64
  oauth2 (0.9.3)
70
65
  faraday (>= 0.8, < 0.10)
71
66
  jwt (~> 0.1.8)
72
67
  multi_json (~> 1.3)
73
68
  multi_xml (~> 0.5)
74
69
  rack (~> 1.2)
75
- parser (2.2.2.6)
70
+ parser (2.2.3.0)
76
71
  ast (>= 1.1, < 3.0)
77
72
  poltergeist (1.4.1)
78
73
  capybara (~> 2.1.0)
@@ -80,20 +75,13 @@ GEM
80
75
  multi_json (~> 1.0)
81
76
  websocket-driver (>= 0.2.0)
82
77
  powerpack (0.1.1)
83
- pry (0.10.3)
84
- coderay (~> 1.1.0)
85
- method_source (~> 0.8.1)
86
- slop (~> 3.4)
87
- pry-byebug (3.2.0)
88
- byebug (~> 5.0)
89
- pry (~> 0.10)
90
78
  pullreview-coverage (0.0.5)
91
79
  certifi
92
80
  simplecov (>= 0.7.1, < 1.0.0)
93
- rack (1.5.2)
81
+ rack (1.6.4)
94
82
  rack-protection (1.5.0)
95
83
  rack
96
- rack-test (0.6.2)
84
+ rack-test (0.6.3)
97
85
  rack (>= 1.0)
98
86
  rainbow (2.0.0)
99
87
  rake (10.2.2)
@@ -113,7 +101,7 @@ GEM
113
101
  diff-lcs (>= 1.2.0, < 2.0)
114
102
  rspec-support (~> 3.3.0)
115
103
  rspec-support (3.3.0)
116
- rubocop (0.34.0)
104
+ rubocop (0.34.2)
117
105
  astrolabe (~> 1.3)
118
106
  parser (>= 2.2.2.5, < 3.0)
119
107
  powerpack (~> 0.1)
@@ -135,7 +123,6 @@ GEM
135
123
  rack (~> 1.4)
136
124
  rack-protection (~> 1.4)
137
125
  tilt (~> 1.3, >= 1.3.4)
138
- slop (3.6.0)
139
126
  thread_safe (0.3.5)
140
127
  tilt (1.4.1)
141
128
  tzinfo (1.2.2)
@@ -153,19 +140,18 @@ PLATFORMS
153
140
  ruby
154
141
 
155
142
  DEPENDENCIES
156
- activesupport
157
- capybara
143
+ activesupport (~> 4)
144
+ capybara (~> 2)
158
145
  codeclimate-test-reporter
159
- github-markup
160
- jeweler
146
+ github-markup (~> 1.4)
147
+ jeweler (~> 2.0)
161
148
  poltergeist
162
- pry-byebug
163
149
  pullreview-coverage
164
- redcarpet
150
+ redcarpet (~> 3.3)
165
151
  rspec
166
- rubocop
152
+ rubocop (~> 0.34)
167
153
  simplecov
168
154
  sinatra
169
- wait
155
+ wait (~> 0)
170
156
  watir-webdriver
171
- yard
157
+ yard (~> 0.8)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Code Climate](https://codeclimate.com/github/Ladtech/page_magic/badges/gpa.svg)](https://codeclimate.com/github/Ladtech/page_magic) [![Test Coverage](https://codeclimate.com/github/Ladtech/page_magic/badges/coverage.svg)](https://codeclimate.com/github/Ladtech/page_magic/coverage) [![PullReview stats](https://www.pullreview.com/github/Ladtech/page_magic/badges/master.svg?)](https://www.pullreview.com/github/Ladtech/page_magic/reviews/master)
1
+ [![Circle CI](https://circleci.com/gh/Ladtech/page_magic.svg?style=shield&circle-token=49c8f6869c1e0dc6f3b368e6e22a11fcea3aab8a)](https://circleci.com/gh/Ladtech/page_magic) [![Code Climate](https://codeclimate.com/github/Ladtech/page_magic/badges/gpa.svg)](https://codeclimate.com/github/Ladtech/page_magic) [![Test Coverage](https://codeclimate.com/github/Ladtech/page_magic/badges/coverage.svg)](https://codeclimate.com/github/Ladtech/page_magic/coverage) [![PullReview stats](https://www.pullreview.com/github/Ladtech/page_magic/badges/master.svg?)](https://www.pullreview.com/github/Ladtech/page_magic/reviews/master)
2
2
  #PageMagic
3
3
  PageMagic is an API for testing web applications.
4
4
 
@@ -12,7 +12,7 @@ Wouldn't it be great if there was a framework that could:
12
12
 
13
13
  Well PageMagic might just be the answer!
14
14
 
15
- Give it a try and let us know what you think! It's there will undoubtedly be things that can be improved and issues that we are not aware of so your feedback/pull requests are greatly appreciated!
15
+ Give it a try and let us know what you think! There will undoubtedly be things that can be improved and issues that we are not aware of so your feedback/pull requests are greatly appreciated!
16
16
 
17
17
  # Installation
18
18
  `gem install page_magic --pre`
@@ -101,8 +101,20 @@ class MessageView
101
101
  include PageMagic
102
102
  end
103
103
  ```
104
+ ### Hooks
105
+ PageMagic lets you define an on_load hook for your pages. This lets you right any custom wait logic you might need
106
+ before letting execution continue.
107
+ ```ruby
108
+ class LoginPage
109
+ # ... code defining elements as shown above
110
+
111
+ on_load do
112
+ # wait code here
113
+ end
114
+ end
115
+ ```
104
116
 
105
- ## Helper methods
117
+ ### Helper methods
106
118
  Using elements that are defined on a page is great, but if you are enacting a procedure through interacting with a few of them then your code could end up with some pretty repetitive code. In this case you can define helper methods instead.
107
119
 
108
120
  In the above [example](#an example) we used a helper called `login`.
@@ -157,15 +169,15 @@ Here we have defined the 'message' element using a block that takes subject argu
157
169
  session.message(subject: 'test message')
158
170
  ```
159
171
  ## Interaction hooks
160
- Frequently, you are going to have to work with pages that make heavy use of ajax. This means that just because you've clicked something, it doesn't mean that the action is finished. For these occasions PageMagic provides `before` and `after` hooks that you use to perform custom actions and wait for things to happen. In the case of our web based mail client, we could imagine that when deleting the email, a fancy spinner is displayed whilst the application sends an ajax request to have the message deleted. In this case we wouldn't want to proceed until this has disappeared.
172
+ Frequently, you are going to have to work with pages that make heavy use of ajax. This means that just because you've clicked something, it doesn't mean that the action is finished. For these occasions PageMagic provides `before_events` and `after_events` hooks that you use to perform custom actions and wait for things to happen. In the case of our web based mail client, we could imagine that when deleting the email, a fancy spinner is displayed whilst the application sends an ajax request to have the message deleted. In this case we wouldn't want to proceed until this has disappeared.
161
173
 
162
174
  ```ruby
163
175
  class MessagePage
164
176
  include PageMagic
165
177
  ## code defining other elements, such as subject and body
166
178
 
167
- link(:delete, id: 'delete-message') do
168
- after do
179
+ link(:delete id: 'delete-message') do
180
+ after_events do
169
181
  wait_until{fancy_animation_has_disappeared?}
170
182
  end
171
183
  end
data/Rakefile CHANGED
@@ -18,4 +18,4 @@ end
18
18
 
19
19
  Jeweler::RubygemsDotOrgTasks.new
20
20
 
21
- task default: :spec
21
+ task default: [:spec, 'rubocop:auto_correct']
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha18
1
+ 1.0.0.alpha19
data/circle.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  test:
2
2
  override:
3
- - bundle exec rake spec
3
+ - bundle exec rake
@@ -0,0 +1,20 @@
1
+ module PageMagic
2
+ # module ClassMethods - contains class level methods for PageObjects
3
+ module ClassMethods
4
+ DEFAULT_ON_LOAD = proc {}
5
+
6
+ # getter setter for storing the page url
7
+ # @param [String] url the url of the page
8
+ def url(url = nil)
9
+ @url = url if url
10
+ @url
11
+ end
12
+
13
+ # sets block to run when page has loaded
14
+ # if one has not been set on the page object class it will return a default block that does nothing
15
+ def on_load(&block)
16
+ return @on_load || DEFAULT_ON_LOAD unless block
17
+ @on_load = block
18
+ end
19
+ end
20
+ end
@@ -2,15 +2,36 @@ module PageMagic
2
2
  # class Driver - instances are factories for drivers used by PageMagic
3
3
  class Driver
4
4
  attr_reader :supported_browsers, :handler
5
+ # Creates a driver definition
6
+ # @example
7
+ # Driver.new do |rack_application, options|
8
+ # require 'capybara/driver_class'
9
+ # Capybara::Driver::Class.new(app, options)
10
+ # end
11
+ # @yield[rack_application, options, browser_name]
12
+ # @yieldparam [Object] rack_application rack compatible application
13
+ # @yieldparam [Hash] options hash containing driver specific options
14
+ # @yieldparam [Symbol] browser_name the name of the required browser name
15
+ # @param [*Symbol] supported_browsers list of browsers names. These are the names that
16
+ # you will refer to them by when creating a session
17
+ # @yieldreturn [Object] Capybara compliant driver
5
18
  def initialize(*supported_browsers, &block)
6
19
  @handler = block
7
20
  @supported_browsers = supported_browsers
8
21
  end
9
22
 
23
+ # Determines if the given browser name is supported by this driver definition
24
+ # @param [Symbol] browser name of browser
25
+ # @return [Boolean] true if definition supports the given driver name
10
26
  def support?(browser)
11
27
  supported_browsers.include?(browser)
12
28
  end
13
29
 
30
+ # Build a new driver instance based on this definition
31
+ # @param [Object] app - rack compatible application
32
+ # @param [Symbol] browser name of required browser
33
+ # @param [Hash] options driver specific options
34
+ # @return [Object] Capybara compliant driver instance
14
35
  def build(app, browser:, options:{})
15
36
  handler.call(app, options, browser)
16
37
  end
@@ -7,10 +7,14 @@ module PageMagic
7
7
  @all ||= []
8
8
  end
9
9
 
10
+ # Make a driver available for selection when creating calling {PageMagic.session}
11
+ # @param [Driver] driver driver definition
10
12
  def register(driver)
11
13
  all << driver
12
14
  end
13
15
 
16
+ # Find a driver definition based on its registered name
17
+ # @param [Symbol] browser registered name of the required browser
14
18
  def find(browser)
15
19
  all.find { |driver| driver.support?(browser) }
16
20
  end
@@ -27,6 +31,9 @@ module PageMagic
27
31
  end
28
32
  end
29
33
 
34
+ # returns true if this driver instance is equal to the supplied object
35
+ # @param [Object] other subject of equality check
36
+ # @return [Boolean] true if the object is a match
30
37
  def ==(other)
31
38
  other.is_a?(Drivers) && all == other.all
32
39
  end
@@ -2,6 +2,8 @@ module PageMagic
2
2
  class Element
3
3
  # module SelectorMethods - adds method for getting and setting an element selector
4
4
  module SelectorMethods
5
+ # Gets/Sets a selector
6
+ # @param [Hash] selector method for locating the browser element. E.g. text: 'the text'
5
7
  def selector(selector = nil)
6
8
  return @selector unless selector
7
9
  @selector = selector
@@ -8,13 +8,13 @@ module PageMagic
8
8
  EVENT_TYPES = [:set, :select, :select_option, :unselect_option, :click]
9
9
  DEFAULT_HOOK = proc {}.freeze
10
10
 
11
- attr_reader :type, :name, :parent_page_element, :browser_element
11
+ attr_reader :type, :name, :parent_page_element
12
12
 
13
13
  include Elements, MethodObserver, SelectorMethods
14
14
  extend Elements, SelectorMethods
15
15
 
16
- def initialize(name, parent_page_element, type: :element, selector: {}, browser_element: nil, &block)
17
- @browser_element = browser_element
16
+ def initialize(name, parent_page_element, type: :element, selector: {}, prefetched_browser_element: nil, &block)
17
+ @browser_element = prefetched_browser_element
18
18
  @selector = selector
19
19
 
20
20
  @before_hook = DEFAULT_HOOK
@@ -26,29 +26,51 @@ module PageMagic
26
26
  expand(&block) if block
27
27
  end
28
28
 
29
+ # expand the element definition by evaluating the given block in the scope of this object
30
+ # @param [*Object] args list of arguments to be supplied to the given block
29
31
  def expand(*args, &block)
30
32
  instance_exec(*args, &block)
31
33
  self
32
34
  end
33
35
 
36
+ # @return [Boolean] returns true if this element contains helper methods or sub element definitions
34
37
  def section?
35
38
  !element_definitions.empty? || singleton_methods_added?
36
39
  end
37
40
 
41
+ # @return [Object] returns the overall of the parent page element. this will ultimately be the {Session} wrapping
42
+ # Capybara session
38
43
  def session
39
44
  @parent_page_element.session
40
45
  end
41
46
 
42
- def before(&block)
47
+ # Get/Sets the block of code to be run before an event is triggered on an element. See {EVENT_TYPES} for the list of
48
+ # events that this block will be triggered for. The block is run in the scope of the element object
49
+ def before_events(&block)
43
50
  return @before_hook unless block
44
51
  @before_hook = block
45
52
  end
46
53
 
47
- def after(&block)
54
+ # Get/Sets the block of code to be run after an event is triggered on an element. See {EVENT_TYPES} for the list of
55
+ # events that this block will be triggered for. The block is run in the scope of the element object
56
+ def after_events(&block)
48
57
  return @after_hook unless block
49
58
  @after_hook = block
50
59
  end
51
60
 
61
+ # @return [Object] the Capybara browser element that this element definition is tied to.
62
+ def browser_element
63
+ return @browser_element if @browser_element
64
+
65
+ fail UndefinedSelectorException, 'Pass a locator/define one on the class' if selector.empty?
66
+
67
+ query = Query.find(type).build(query_selector, query_options)
68
+
69
+ @browser_element = parent_browser_element.find(*query).tap do |raw_element|
70
+ wrap_events(raw_element)
71
+ end
72
+ end
73
+
52
74
  def method_missing(method, *args, &block)
53
75
  ElementContext.new(self).send(method, args.first, &block)
54
76
  rescue ElementMissingException
@@ -64,22 +86,10 @@ module PageMagic
64
86
  super || element_context.respond_to?(*args) || browser_element.respond_to?(*args)
65
87
  end
66
88
 
67
- def browser_element(*_args)
68
- return @browser_element if @browser_element
69
-
70
- fail UndefinedSelectorException, 'Pass a locator/define one on the class' if selector.empty?
71
-
72
- query = Query.find(type).build(query_selector, query_options)
73
-
74
- @browser_element = parent_browser_element.find(*query).tap do |raw_element|
75
- wrap_events(raw_element)
76
- end
77
- end
78
-
79
89
  def ==(other)
80
90
  return false unless other.is_a?(Element)
81
- this = [type, name, selector, before, after]
82
- this == [other.type, other.name, other.selector, other.before, other.after]
91
+ this = [type, name, selector, before_events, after_events]
92
+ this == [other.type, other.name, other.selector, other.before_events, other.after_events]
83
93
  end
84
94
 
85
95
  private
@@ -101,8 +111,8 @@ module PageMagic
101
111
  next unless raw_element.respond_to?(action_method)
102
112
  apply_hooks(raw_element: raw_element,
103
113
  capybara_method: action_method,
104
- before_hook: before,
105
- after_hook: after)
114
+ before_hook: before_events,
115
+ after_hook: after_events)
106
116
  end
107
117
  end
108
118
 
@@ -2,18 +2,29 @@ require 'active_support/inflector'
2
2
  module PageMagic
3
3
  # module Elements - contains methods that add element definitions to the objects it is mixed in to
4
4
  module Elements
5
+ # hooks for objects that inherit classes that include the Elements module
6
+ module InheritanceHooks
7
+ # Copies parent element definitions on to subclass
8
+ # @param [Class] clazz - inheritting class
9
+ def inherited(clazz)
10
+ clazz.element_definitions.merge!(element_definitions)
11
+ end
12
+ end
13
+
5
14
  INVALID_METHOD_NAME_MSG = 'a method already exists with this method name'
6
15
  TYPES = [:text_field, :button, :link, :checkbox, :select_list, :radios, :textarea]
7
16
 
8
17
  class << self
9
18
  def included(clazz)
10
- def clazz.inherited(clazz)
11
- clazz.element_definitions.merge!(element_definitions)
12
- end
19
+ clazz.extend(InheritanceHooks)
13
20
  end
14
21
  alias_method :extended, :included
15
22
  end
16
23
 
24
+ # Get all {Element} definitions
25
+ # @param [Object] browser_element capybara browser element from which the definitions can be sourced
26
+ # @param [*Object] args argument to be passed to block used to expand the {Element} definitions
27
+ # @return [Array] list of {Element} defintions
17
28
  def elements(browser_element, *args)
18
29
  element_definitions.values.collect { |definition| definition.call(browser_element, *args) }
19
30
  end
@@ -54,7 +65,7 @@ module PageMagic
54
65
  name = compute_name(args, section_class)
55
66
 
56
67
  options = { type: __callee__ }
57
- selector ? options[:selector] = selector : options[:browser_element] = args.delete_at(0)
68
+ selector ? options[:selector] = selector : options[:prefetched_browser_element] = args.delete_at(0)
58
69
 
59
70
  add_element_definition(name) do |parent_browser_element, *e_args|
60
71
  section_class.new(name, parent_browser_element, options).expand(*e_args, &block)
@@ -63,6 +74,8 @@ module PageMagic
63
74
 
64
75
  TYPES.each { |type| alias_method type, :element }
65
76
 
77
+ # @return [Hash] element definition names mapped to blocks that can be used to create unique instances of
78
+ # and {Element} definitions
66
79
  def element_definitions
67
80
  @element_definitions ||= {}
68
81
  end
@@ -12,23 +12,31 @@ module PageMagic
12
12
  @browser_element = browser
13
13
  end
14
14
 
15
+ # @return the current page title
15
16
  def title
16
17
  browser.title
17
18
  end
18
19
 
20
+ # check for the presense of specific text on the page
21
+ # @param [String] string the string to check for
22
+ # @return [Boolean]
19
23
  def text_on_page?(string)
20
24
  text.downcase.include?(string.downcase)
21
25
  end
22
26
 
27
+ # Visit this page based on the class level registered url
23
28
  def visit
24
29
  browser.visit self.class.url
25
- self
30
+ execute_on_load
26
31
  end
27
32
 
33
+ # @return the page text
28
34
  def text
29
35
  browser.text
30
36
  end
31
37
 
38
+ # proxy to the defined page element definitions
39
+ # @return [Object] the result of accessing the requested page element through its definition
32
40
  def method_missing(method, *args)
33
41
  element_context.send(method, *args)
34
42
  end
@@ -37,10 +45,20 @@ module PageMagic
37
45
  super || element_context.respond_to?(*args)
38
46
  end
39
47
 
48
+ # @return [Array] class level defined element definitions
40
49
  def element_definitions
41
50
  self.class.element_definitions
42
51
  end
43
52
 
53
+ # executes block stored using {ClassMethods#on_load} against self
54
+ # @return [Element] self
55
+ def execute_on_load
56
+ instance_eval(&self.class.on_load)
57
+ self
58
+ end
59
+
60
+ private
61
+
44
62
  def element_context
45
63
  ElementContext.new(self)
46
64
  end
@@ -4,6 +4,7 @@ module PageMagic
4
4
  class Session
5
5
  URL_MISSING_MSG = 'a path must be mapped or a url supplied'
6
6
  REGEXP_MAPPING_MSG = 'URL could not be derived because mapping is a Regexp'
7
+ INVALID_MAPPING_MSG = 'mapping must be a string or regexp'
7
8
 
8
9
  attr_reader :raw_session, :transitions
9
10
 
@@ -58,7 +59,7 @@ module PageMagic
58
59
  else
59
60
  fail InvalidURLException, URL_MISSING_MSG
60
61
  end
61
- @current_page = page.new(self) if page
62
+ @current_page = page.new(self).execute_on_load if page
62
63
  self
63
64
  end
64
65
 
@@ -104,18 +105,16 @@ module PageMagic
104
105
 
105
106
  def find_mapped_page(path)
106
107
  mapping = transitions.keys.find do |key|
107
- string_matches?(path, key)
108
+ matches?(path, key)
108
109
  end
109
110
  transitions[mapping]
110
111
  end
111
112
 
112
- def string_matches?(string, matcher)
113
+ def matches?(string, matcher)
113
114
  if matcher.is_a?(Regexp)
114
115
  string =~ matcher
115
- elsif matcher.is_a?(String)
116
- string == matcher
117
116
  else
118
- false
117
+ string == matcher
119
118
  end
120
119
  end
121
120
  end
data/lib/page_magic.rb CHANGED
@@ -4,6 +4,7 @@ require 'page_magic/exceptions'
4
4
  require 'page_magic/session'
5
5
  require 'page_magic/instance_methods'
6
6
  require 'page_magic/elements'
7
+ require 'page_magic/class_methods'
7
8
  require 'page_magic/element_context'
8
9
  require 'page_magic/element'
9
10
  require 'page_magic/drivers'
@@ -28,13 +29,8 @@ module PageMagic
28
29
 
29
30
  def included(clazz)
30
31
  clazz.class_eval do
31
- def self.url(url = nil)
32
- @url = url if url
33
- @url
34
- end
35
-
36
32
  include(InstanceMethods)
37
- extend(Elements)
33
+ extend(Elements, ClassMethods)
38
34
  end
39
35
  end
40
36
  end
data/spec/element_spec.rb CHANGED
@@ -39,7 +39,10 @@ module PageMagic
39
39
 
40
40
  describe '#respond_to?' do
41
41
  subject do
42
- described_class.new(:name, Object.new, type: :element, browser_element: double(element_method: '')) do
42
+ described_class.new(:name,
43
+ Object.new,
44
+ type: :element,
45
+ prefetched_browser_element: double(element_method: '')) do
43
46
  element :sub_element, css: '.sub-element'
44
47
  end
45
48
  end
@@ -59,6 +62,9 @@ module PageMagic
59
62
  describe '#browser_element' do
60
63
  let!(:browser) { double('browser') }
61
64
 
65
+ it 'calls the on_load hook' do
66
+ end
67
+
62
68
  context 'options supplied to selector' do
63
69
  it 'passes them on to the cappybara finder method' do
64
70
  options = { count: 1 }
@@ -112,7 +118,7 @@ module PageMagic
112
118
  end
113
119
 
114
120
  it 'should return a prefetched value' do
115
- element = described_class.new(:help, page, type: :link, browser_element: :prefetched_object)
121
+ element = described_class.new(:help, page, type: :link, prefetched_browser_element: :prefetched_object)
116
122
  expect(element.browser_element).to eq(:prefetched_object)
117
123
  end
118
124
 
@@ -185,7 +191,7 @@ module PageMagic
185
191
  describe 'hooks' do
186
192
  subject do
187
193
  described_class.new(:my_button, page, type: :button, selector: { id: 'my_button' }) do
188
- before do
194
+ before_events do
189
195
  call_in_before_hook
190
196
  end
191
197
  end
@@ -201,7 +207,7 @@ module PageMagic
201
207
  context 'method called in before hook' do
202
208
  subject do
203
209
  described_class.new(:my_button, page, type: :button, selector: { id: 'my_button' }) do
204
- after do
210
+ after_events do
205
211
  call_in_after_hook
206
212
  end
207
213
  end
@@ -0,0 +1,29 @@
1
+ module PageMagic
2
+ describe ClassMethods do
3
+ subject do
4
+ Object.new.tap { |o| o.extend(described_class) }
5
+ end
6
+ describe '#url' do
7
+ it 'get/sets a value' do
8
+ subject.url(:url)
9
+ expect(subject.url).to eq(:url)
10
+ end
11
+ end
12
+
13
+ describe 'on_load' do
14
+ context 'block not set' do
15
+ it 'returns a default block' do
16
+ expect(subject.on_load).to be(described_class::DEFAULT_ON_LOAD)
17
+ end
18
+ end
19
+
20
+ context 'block set' do
21
+ it 'returns that block' do
22
+ expected_block = proc {}
23
+ subject.on_load(&expected_block)
24
+ expect(subject.on_load).to be(expected_block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -120,7 +120,10 @@ module PageMagic
120
120
  describe 'location' do
121
121
  context 'a prefetched object' do
122
122
  it 'should add a section' do
123
- expected_section = Element.new(:page_section, parent_page_element, type: :element, browser_element: :object)
123
+ expected_section = Element.new(:page_section,
124
+ parent_page_element,
125
+ type: :element,
126
+ prefetched_browser_element: :object)
124
127
  page_elements.element :page_section, :object
125
128
  expect(expected_section).to eq(page_elements.elements(parent_page_element).first)
126
129
  end
@@ -130,7 +133,7 @@ module PageMagic
130
133
  describe 'session handle' do
131
134
  it 'should be on instances created from a class' do
132
135
  browser_element = double(:browser_element, find: :browser_element)
133
- parent = double('parent', session: :current_session, browser_element: browser_element)
136
+ parent = double('parent', session: :current_session, prefetched_browser_element: browser_element)
134
137
  page_elements.element :page_section, selector
135
138
 
136
139
  section = page_elements.element_definitions[:page_section].call(parent)
@@ -141,7 +144,7 @@ module PageMagic
141
144
  it 'should be on instances created dynamically using the section method' do
142
145
  browser_element = double('browser_element')
143
146
  allow(browser_element).to receive(:find)
144
- parent = double('parent', session: :current_session, browser_element: browser_element)
147
+ parent = double('parent', session: :current_session, prefetched_browser_element: browser_element)
145
148
 
146
149
  page_elements.element :page_section, css: :selector do
147
150
  end
@@ -1,13 +1,33 @@
1
1
  module PageMagic
2
2
  describe InstanceMethods do
3
3
  include_context :webapp_fixture
4
- subject do
5
- clazz = Class.new do
4
+
5
+ let(:page_class) do
6
+ Class.new do
6
7
  include PageMagic
7
8
  url '/page1'
8
9
  link(:next_page, text: 'next page')
9
10
  end
10
- clazz.new.tap(&:visit)
11
+ end
12
+
13
+ subject do
14
+ page_class.new.tap(&:visit)
15
+ end
16
+
17
+ describe 'execute_on_load' do
18
+ it 'runs the on_load_hook in the context of self' do
19
+ instance = subject
20
+ page_class.on_load do
21
+ extend RSpec::Matchers
22
+ expect(self).to be(instance)
23
+ end
24
+
25
+ subject.execute_on_load
26
+ end
27
+
28
+ it 'returns self' do
29
+ expect(subject.execute_on_load).to be(subject)
30
+ end
11
31
  end
12
32
 
13
33
  context '#respond_to?' do
@@ -20,10 +40,15 @@ module PageMagic
20
40
  end
21
41
  end
22
42
 
23
- describe 'visit' do
43
+ describe '#visit' do
24
44
  it 'goes to the class define url' do
25
45
  expect(subject.session.current_path).to eq('/page1')
26
46
  end
47
+
48
+ it 'runs the on load handler' do
49
+ expect(subject).to receive(:execute_on_load).and_call_original
50
+ subject.visit
51
+ end
27
52
  end
28
53
 
29
54
  describe 'session' do
@@ -77,34 +77,54 @@ module PageMagic
77
77
  end
78
78
  end
79
79
 
80
+ describe '#wait' do
81
+ it 'passes the supplied block to the wait api' do
82
+ block = proc { :executed }
83
+ allow_any_instance_of(Wait).to receive(:until).and_call_original
84
+ expect(subject.wait_until(&block)).to eq(:executed)
85
+ end
86
+ end
87
+
80
88
  describe '#visit' do
81
89
  let(:session) do
82
90
  allow(browser).to receive(:visit)
83
91
  PageMagic::Session.new(browser, url)
84
92
  end
85
93
 
86
- it 'sets the current page' do
87
- session.define_page_mappings '/page' => page
88
- session.visit(page)
89
- expect(session.current_page).to be_a(page)
90
- end
94
+ context 'page supplied' do
95
+ it 'sets the current page' do
96
+ session.define_page_mappings '/page' => page
97
+ session.visit(page)
98
+ expect(session.current_page).to be_a(page)
99
+ end
91
100
 
92
- it 'uses the current url and the path in the page mappings' do
93
- session.define_page_mappings '/page' => page
94
- expect(browser).to receive(:visit).with("#{browser.current_url}/page")
95
- session.visit(page)
96
- end
101
+ it 'uses the current url and the path in the page mappings' do
102
+ session.define_page_mappings '/page' => page
103
+ expect(browser).to receive(:visit).with("#{browser.current_url}/page")
104
+ session.visit(page)
105
+ end
97
106
 
98
- context 'no mappings found' do
99
- it 'raises an error' do
100
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
107
+ context 'no mappings found' do
108
+ it 'raises an error' do
109
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
110
+ end
111
+ end
112
+
113
+ context 'mapping is a regular expression' do
114
+ it 'raises an error' do
115
+ session.define_page_mappings(/mapping/ => page)
116
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
117
+ end
101
118
  end
102
- end
103
119
 
104
- context 'mapping is a regular expression' do
105
- it 'raises an error' do
106
- session.define_page_mappings(/mapping/ => page)
107
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
120
+ it 'calls the onload hook' do
121
+ on_load_hook_called = false
122
+ page.on_load do
123
+ on_load_hook_called = true
124
+ end
125
+ session.define_page_mappings('/page' => page)
126
+ session.visit(page)
127
+ expect(on_load_hook_called).to eq(true)
108
128
  end
109
129
  end
110
130
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  Bundler.require
2
2
  $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
3
- require 'pry-byebug'
4
3
  require 'support/shared_contexts'
5
4
 
6
5
  require 'simplecov' if ENV['coverage']
metadata CHANGED
@@ -1,141 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: page_magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha18
4
+ version: 1.0.0.alpha19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leon Davis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-02 00:00:00.000000000 Z
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '4'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '4'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: wait
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: jeweler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '2.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '2.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.34'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: pry-byebug
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
82
+ version: '0.34'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: yard
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - ">="
87
+ - - "~>"
102
88
  - !ruby/object:Gem::Version
103
- version: '0'
89
+ version: '0.8'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
- - - ">="
94
+ - - "~>"
109
95
  - !ruby/object:Gem::Version
110
- version: '0'
96
+ version: '0.8'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: redcarpet
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
- - - ">="
101
+ - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: '0'
103
+ version: '3.3'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
- - - ">="
108
+ - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: '0'
110
+ version: '3.3'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: github-markup
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
- - - ">="
115
+ - - "~>"
130
116
  - !ruby/object:Gem::Version
131
- version: '0'
117
+ version: '1.4'
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
- - - ">="
122
+ - - "~>"
137
123
  - !ruby/object:Gem::Version
138
- version: '0'
124
+ version: '1.4'
139
125
  description: Framework for modeling and interacting with webpages which wraps capybara
140
126
  email: info@lad-tech.com
141
127
  executables: []
@@ -158,6 +144,7 @@ files:
158
144
  - VERSION
159
145
  - circle.yml
160
146
  - lib/page_magic.rb
147
+ - lib/page_magic/class_methods.rb
161
148
  - lib/page_magic/driver.rb
162
149
  - lib/page_magic/drivers.rb
163
150
  - lib/page_magic/drivers/poltergeist.rb
@@ -176,6 +163,7 @@ files:
176
163
  - page_magic.gemspec
177
164
  - spec/element_spec.rb
178
165
  - spec/member_methods_spec.rb
166
+ - spec/page_magic/class_methods_spec.rb
179
167
  - spec/page_magic/driver_spec.rb
180
168
  - spec/page_magic/drivers/poltergeist_spec.rb
181
169
  - spec/page_magic/drivers/rack_test_spec.rb