page_magic 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +69 -53
- data/README.md +135 -61
- data/VERSION +1 -1
- data/lib/page_magic/element/locators.rb +2 -1
- data/lib/page_magic/element.rb +46 -21
- data/lib/page_magic/element_context.rb +2 -2
- data/lib/page_magic/element_definition_builder.rb +2 -3
- data/lib/page_magic/elements.rb +19 -10
- data/lib/page_magic/session.rb +6 -2
- data/lib/page_magic/watchers.rb +1 -0
- data/page_magic.gemspec +3 -3
- data/spec/element_spec.rb +105 -21
- data/spec/page_magic/elements_spec.rb +1 -1
- data/spec/page_magic/watchers_spec.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 262a69afc9f016ea5dfb07cd11c90bf9efc29a33
|
4
|
+
data.tar.gz: 6a822ce3efb1abcf1dfc73d829a6b5604db5b518
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17b6e79c778f473d8a4cc2ca83fc36e02bb31b0b2e6686204afd92f4298388d0914150c4e6002a3f6883b808ecab5161d1c6fe3dea6bd552a6be0cfb6b8611fc
|
7
|
+
data.tar.gz: e5dacc0762ff7ec21f303247460597dc201ddaf409c45a12e16ee57bdc7cfaa6c1659375335be10b840f45b852b523ade1557516367d43ca02aef6dded24c44c
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'capybara', '2.5
|
3
|
+
gem 'capybara', '>= 2.5'
|
4
4
|
gem 'activesupport', '~> 4'
|
5
5
|
gem 'wait', '~> 0'
|
6
6
|
|
@@ -12,6 +12,7 @@ group :test do
|
|
12
12
|
gem 'poltergeist'
|
13
13
|
gem 'codeclimate-test-reporter', group: :test, require: nil
|
14
14
|
gem 'pullreview-coverage', require: false
|
15
|
+
gem 'cucumber'
|
15
16
|
end
|
16
17
|
|
17
18
|
group :development do
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
GEM
|
2
2
|
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activesupport (4.2.
|
4
|
+
activesupport (4.2.5)
|
5
5
|
i18n (~> 0.7)
|
6
6
|
json (~> 1.7, >= 1.7.7)
|
7
7
|
minitest (~> 5.1)
|
8
8
|
thread_safe (~> 0.3, >= 0.3.4)
|
9
9
|
tzinfo (~> 1.1)
|
10
|
-
addressable (2.3.
|
10
|
+
addressable (2.3.8)
|
11
11
|
ast (2.1.0)
|
12
12
|
astrolabe (1.3.1)
|
13
13
|
parser (~> 2.2)
|
@@ -19,27 +19,40 @@ GEM
|
|
19
19
|
rack-test (>= 0.5.4)
|
20
20
|
xpath (~> 2.0)
|
21
21
|
certifi (2015.08.10)
|
22
|
-
childprocess (0.
|
22
|
+
childprocess (0.5.8)
|
23
23
|
ffi (~> 1.0, >= 1.0.11)
|
24
24
|
cliver (0.3.2)
|
25
25
|
codeclimate-test-reporter (0.4.8)
|
26
26
|
simplecov (>= 0.7.1, < 1.0.0)
|
27
|
+
cucumber (2.1.0)
|
28
|
+
builder (>= 2.1.2)
|
29
|
+
cucumber-core (~> 1.3.0)
|
30
|
+
diff-lcs (>= 1.1.3)
|
31
|
+
gherkin3 (~> 3.1.0)
|
32
|
+
multi_json (>= 1.7.5, < 2.0)
|
33
|
+
multi_test (>= 0.1.2)
|
34
|
+
cucumber-core (1.3.0)
|
35
|
+
gherkin3 (~> 3.1.0)
|
36
|
+
descendants_tracker (0.0.4)
|
37
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
27
38
|
diff-lcs (1.2.5)
|
28
39
|
docile (1.1.5)
|
29
|
-
faraday (0.
|
30
|
-
multipart-post (
|
31
|
-
ffi (1.9.
|
32
|
-
|
40
|
+
faraday (0.9.2)
|
41
|
+
multipart-post (>= 1.2, < 3)
|
42
|
+
ffi (1.9.10)
|
43
|
+
gherkin3 (3.1.2)
|
44
|
+
git (1.2.9.1)
|
33
45
|
github-markup (1.4.0)
|
34
|
-
github_api (0.
|
35
|
-
addressable
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
github_api (0.12.4)
|
47
|
+
addressable (~> 2.3)
|
48
|
+
descendants_tracker (~> 0.0.4)
|
49
|
+
faraday (~> 0.8, < 0.10)
|
50
|
+
hashie (>= 3.4)
|
51
|
+
multi_json (>= 1.7.5, < 2.0)
|
52
|
+
nokogiri (~> 1.6.6)
|
40
53
|
oauth2
|
41
|
-
hashie (
|
42
|
-
highline (1.
|
54
|
+
hashie (3.4.3)
|
55
|
+
highline (1.7.8)
|
43
56
|
i18n (0.7.0)
|
44
57
|
jeweler (2.0.1)
|
45
58
|
builder
|
@@ -50,26 +63,26 @@ GEM
|
|
50
63
|
nokogiri (>= 1.5.10)
|
51
64
|
rake
|
52
65
|
rdoc
|
53
|
-
json (1.8.
|
54
|
-
jwt (
|
55
|
-
multi_json (>= 1.5)
|
66
|
+
json (1.8.3)
|
67
|
+
jwt (1.5.2)
|
56
68
|
mime-types (2.6.2)
|
57
69
|
mini_portile (0.6.2)
|
58
|
-
minitest (5.
|
70
|
+
minitest (5.8.2)
|
59
71
|
multi_json (1.11.2)
|
72
|
+
multi_test (0.1.2)
|
60
73
|
multi_xml (0.5.5)
|
61
|
-
multipart-post (
|
74
|
+
multipart-post (2.0.0)
|
62
75
|
nokogiri (1.6.6.2)
|
63
76
|
mini_portile (~> 0.6.0)
|
64
|
-
oauth2 (0.
|
77
|
+
oauth2 (1.0.0)
|
65
78
|
faraday (>= 0.8, < 0.10)
|
66
|
-
jwt (~>
|
79
|
+
jwt (~> 1.0)
|
67
80
|
multi_json (~> 1.3)
|
68
81
|
multi_xml (~> 0.5)
|
69
82
|
rack (~> 1.2)
|
70
83
|
parser (2.2.3.0)
|
71
84
|
ast (>= 1.1, < 3.0)
|
72
|
-
poltergeist (1.
|
85
|
+
poltergeist (1.8.0)
|
73
86
|
capybara (~> 2.1)
|
74
87
|
cliver (~> 0.3.1)
|
75
88
|
multi_json (~> 1.0)
|
@@ -79,58 +92,60 @@ GEM
|
|
79
92
|
certifi
|
80
93
|
simplecov (>= 0.7.1, < 1.0.0)
|
81
94
|
rack (1.6.4)
|
82
|
-
rack-protection (1.5.
|
95
|
+
rack-protection (1.5.3)
|
83
96
|
rack
|
84
97
|
rack-test (0.6.3)
|
85
98
|
rack (>= 1.0)
|
86
99
|
rainbow (2.0.0)
|
87
|
-
rake (10.
|
88
|
-
rdoc (4.
|
100
|
+
rake (10.4.2)
|
101
|
+
rdoc (4.2.0)
|
89
102
|
json (~> 1.4)
|
90
103
|
redcarpet (3.3.3)
|
91
|
-
rspec (3.
|
92
|
-
rspec-core (~> 3.
|
93
|
-
rspec-expectations (~> 3.
|
94
|
-
rspec-mocks (~> 3.
|
95
|
-
rspec-core (3.
|
96
|
-
rspec-support (~> 3.
|
97
|
-
rspec-expectations (3.
|
104
|
+
rspec (3.4.0)
|
105
|
+
rspec-core (~> 3.4.0)
|
106
|
+
rspec-expectations (~> 3.4.0)
|
107
|
+
rspec-mocks (~> 3.4.0)
|
108
|
+
rspec-core (3.4.0)
|
109
|
+
rspec-support (~> 3.4.0)
|
110
|
+
rspec-expectations (3.4.0)
|
98
111
|
diff-lcs (>= 1.2.0, < 2.0)
|
99
|
-
rspec-support (~> 3.
|
100
|
-
rspec-mocks (3.
|
112
|
+
rspec-support (~> 3.4.0)
|
113
|
+
rspec-mocks (3.4.0)
|
101
114
|
diff-lcs (>= 1.2.0, < 2.0)
|
102
|
-
rspec-support (~> 3.
|
103
|
-
rspec-support (3.
|
104
|
-
rubocop (0.
|
115
|
+
rspec-support (~> 3.4.0)
|
116
|
+
rspec-support (3.4.0)
|
117
|
+
rubocop (0.35.1)
|
105
118
|
astrolabe (~> 1.3)
|
106
|
-
parser (>= 2.2.
|
119
|
+
parser (>= 2.2.3.0, < 3.0)
|
107
120
|
powerpack (~> 0.1)
|
108
121
|
rainbow (>= 1.99.1, < 3.0)
|
109
|
-
ruby-progressbar (~> 1.
|
122
|
+
ruby-progressbar (~> 1.7)
|
123
|
+
tins (<= 1.6.0)
|
110
124
|
ruby-progressbar (1.7.5)
|
111
|
-
rubyzip (
|
112
|
-
selenium-webdriver (2.
|
113
|
-
childprocess (
|
125
|
+
rubyzip (1.1.7)
|
126
|
+
selenium-webdriver (2.48.1)
|
127
|
+
childprocess (~> 0.5)
|
114
128
|
multi_json (~> 1.0)
|
115
|
-
rubyzip (
|
116
|
-
websocket (~> 1.0
|
129
|
+
rubyzip (~> 1.0)
|
130
|
+
websocket (~> 1.0)
|
117
131
|
simplecov (0.10.0)
|
118
132
|
docile (~> 1.1.0)
|
119
133
|
json (~> 1.8)
|
120
134
|
simplecov-html (~> 0.10.0)
|
121
135
|
simplecov-html (0.10.0)
|
122
|
-
sinatra (1.4.
|
136
|
+
sinatra (1.4.6)
|
123
137
|
rack (~> 1.4)
|
124
138
|
rack-protection (~> 1.4)
|
125
|
-
tilt (
|
139
|
+
tilt (>= 1.3, < 3)
|
126
140
|
thread_safe (0.3.5)
|
127
|
-
tilt (
|
141
|
+
tilt (2.0.1)
|
142
|
+
tins (1.6.0)
|
128
143
|
tzinfo (1.2.2)
|
129
144
|
thread_safe (~> 0.1)
|
130
|
-
wait (0.5.
|
131
|
-
watir-webdriver (0.
|
132
|
-
selenium-webdriver (>= 2.
|
133
|
-
websocket (1.
|
145
|
+
wait (0.5.2)
|
146
|
+
watir-webdriver (0.9.1)
|
147
|
+
selenium-webdriver (>= 2.46.2)
|
148
|
+
websocket (1.2.2)
|
134
149
|
websocket-driver (0.6.3)
|
135
150
|
websocket-extensions (>= 0.1.0)
|
136
151
|
websocket-extensions (0.1.2)
|
@@ -143,8 +158,9 @@ PLATFORMS
|
|
143
158
|
|
144
159
|
DEPENDENCIES
|
145
160
|
activesupport (~> 4)
|
146
|
-
capybara (
|
161
|
+
capybara (>= 2.5)
|
147
162
|
codeclimate-test-reporter
|
163
|
+
cucumber
|
148
164
|
github-markup (~> 1.4)
|
149
165
|
jeweler (~> 2.0)
|
150
166
|
poltergeist
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
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)
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/page_magic.svg)](https://badge.fury.io/rb/page_magic) [![Dependency Status](https://gemnasium.com/Ladtech/page_magic.svg)](https://gemnasium.com/Ladtech/page_magic) [![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
|
|
@@ -15,7 +15,7 @@ Well PageMagic might just be the answer!
|
|
15
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
|
# Contents
|
17
17
|
- [Installation](#installation)
|
18
|
-
- [
|
18
|
+
- [Quick Start](#quick-start)
|
19
19
|
- [Defining Pages](#defining-pages)
|
20
20
|
- [Elements](#elements)
|
21
21
|
- [Interacting with elements](#interacting-with-elements)
|
@@ -27,30 +27,45 @@ Give it a try and let us know what you think! There will undoubtedly be things t
|
|
27
27
|
- [On load hook](#on-load-hook)
|
28
28
|
- [Helper Methods](#helper-methods)
|
29
29
|
- [Dynamic Selectors](#dynamic-selectors)
|
30
|
+
- [Starting a session](#starting-a-session)
|
31
|
+
- [Page mapping](#page-mapping)
|
30
32
|
- [Watchers](#watchers)
|
31
33
|
- [Method watchers](#method-watchers)
|
32
34
|
- [Simple watchers](#simple-watchers)
|
33
35
|
- [Custom watchers](#custom-watchers)
|
34
|
-
- [
|
36
|
+
- [Waiting](#waiting)
|
35
37
|
- [Drivers](#drivers)
|
36
|
-
- [
|
38
|
+
- [Cucumber Quick Start](#cucumber-quick-start)
|
37
39
|
|
38
40
|
# Installation
|
39
|
-
`gem install page_magic
|
41
|
+
`gem install page_magic`
|
40
42
|
|
41
|
-
#
|
42
|
-
|
43
|
+
# Quick Start
|
44
|
+
Getting started with PageMagic is as easy, try running this:
|
43
45
|
```ruby
|
44
|
-
|
46
|
+
require 'page_magic'
|
47
|
+
|
48
|
+
class Google
|
49
|
+
include PageMagic
|
50
|
+
url 'https://www.google.com'
|
51
|
+
|
52
|
+
text_field :search_field, name: 'q'
|
53
|
+
button :search_button, name: 'btnG'
|
54
|
+
|
55
|
+
def search term
|
56
|
+
search_field.set term
|
57
|
+
search_button.click
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
google = Google.visit(browser: :chrome)
|
62
|
+
google.search('page_magic')
|
45
63
|
```
|
46
|
-
|
47
|
-
- Chrome and Firefox
|
48
|
-
- poltergeist
|
49
|
-
- RackTest - Read more on testing rack compliant object's directly later on
|
64
|
+
This example defines a simple page to represent Google's search page, visits it and performs a search.
|
50
65
|
|
51
|
-
|
66
|
+
This code models a single page and will let you [interact](#interacting-with-elements) with the [elements](#elements) defined on it as well as use the [helper method](Helpers) we defined.
|
52
67
|
|
53
|
-
|
68
|
+
You can do lots with PageMagic including [mapping pages](#page-mapping) to a [session](#starting-a-session) so that they are fluidly switched in for you. You can even define [hooks](#hooks) to run when ever a element is interacted with. So what are you wating for? there' no place better to start than the [beginning](#defining-pages). Have fun! :)
|
54
69
|
|
55
70
|
# Defining Pages
|
56
71
|
To define something that PageMagic can work with, simply include PageMagic in to a class.
|
@@ -112,7 +127,7 @@ session.message.read.click
|
|
112
127
|
PageMagic allows you to define your own custom elements.
|
113
128
|
```ruby
|
114
129
|
class Nav < PageMagic::Element
|
115
|
-
selector css: '.nav
|
130
|
+
selector css: '.nav'
|
116
131
|
|
117
132
|
element :options, css: '.options' do
|
118
133
|
link(:link1, id: 'link1')
|
@@ -137,7 +152,11 @@ end
|
|
137
152
|
```
|
138
153
|
|
139
154
|
## Hooks
|
140
|
-
PageMagic provides hooks to allow you to interact at the right moments with your pages
|
155
|
+
PageMagic provides hooks to allow you to interact at the right moments with your pages.
|
156
|
+
|
157
|
+
**Note:**
|
158
|
+
- with hooks you may well find PageMagic's [watchers](#watchers) useful.
|
159
|
+
- The following examples wait for actions to happen. You can of course write you own wait code or try out our [wait_until](#waiting) helper:)
|
141
160
|
|
142
161
|
### On load hook
|
143
162
|
PageMagic lets you define an on_load hook for your pages. This lets you write any custom wait logic you might need
|
@@ -147,7 +166,7 @@ class LoginPage
|
|
147
166
|
# ... code defining elements as shown above
|
148
167
|
|
149
168
|
on_load do
|
150
|
-
|
169
|
+
wait_until{login_fields_have_appeared?}
|
151
170
|
end
|
152
171
|
end
|
153
172
|
```
|
@@ -156,7 +175,7 @@ end
|
|
156
175
|
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.
|
157
176
|
|
158
177
|
```ruby
|
159
|
-
class
|
178
|
+
class EmailMessagePage
|
160
179
|
include PageMagic
|
161
180
|
## code defining other elements, such as subject and body
|
162
181
|
|
@@ -206,9 +225,53 @@ Here we have defined the 'message' element using a block that takes subject argu
|
|
206
225
|
session.message(subject: 'test message')
|
207
226
|
```
|
208
227
|
|
228
|
+
# Starting a session
|
229
|
+
To start a PageMagic session simply decide what browser you want to use and pass it to PageMagic's `.session` method
|
230
|
+
```ruby
|
231
|
+
session = PageMagic.session(browser: :chrome, url: 'https://21st-century-mail.com')
|
232
|
+
```
|
233
|
+
|
234
|
+
Your session won't you do much besides navigating to the given url until you have [mapped pages](#page-mapping) to it, so take a look at this next!
|
235
|
+
|
236
|
+
**Note** PageMagic supports having multiple sessions pointed at different urls using different browsers at the same time :)
|
237
|
+
|
238
|
+
## Rack applications and Rack::Test
|
239
|
+
To run a session against a rack application instead of a live site, simply supply the rack application when creating the session
|
240
|
+
```ruby
|
241
|
+
session = PageMagic.session(application: YourRackApp, url: '/path_to_start_at')
|
242
|
+
```
|
243
|
+
|
244
|
+
By default PageMagic uses the Rack::Test driver for capybara however you are free to use any browser you like as long as
|
245
|
+
the [driver is registered](#drivers) for it.
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
session = PageMagic.session(application: YourRackApp, browser: :your_chosen_browser, url: '/path_to_start_at')
|
249
|
+
```
|
250
|
+
|
251
|
+
Out of the box, PageMagic supports the following as parameters to browser:
|
252
|
+
- :chrome
|
253
|
+
- :firefox
|
254
|
+
- :poltergeist
|
255
|
+
- :rack_test
|
256
|
+
|
257
|
+
Under the hood, PageMagic is using [Capybara](https://github.com/jnicklas/capybara) so you can register any Capybara specific driver you want. See [below](#registering-a-custom-driver) for how to do this.
|
258
|
+
|
259
|
+
**Note:** We don't want to impose particular driver versions so PageMagic does not list any as dependencies. Therefore you will need add the requiste gem to your Gemfile.
|
260
|
+
|
261
|
+
# Page mapping
|
262
|
+
With PageMagic you can map which pages should be used to handle which URL paths. This is a pretty killer feature that will remove a lot of the juggling and bring back fluency to your code!
|
263
|
+
```ruby
|
264
|
+
# define what pages map to what
|
265
|
+
browser.define_page_mappings %r{/messages/\d+} => MessagePage,
|
266
|
+
'/login' => LoginPage,
|
267
|
+
'/' => MailBox
|
268
|
+
```
|
269
|
+
You can use even use regular expressions to map multiple paths to the same page. In the above example we are mapping paths that that starts with '/messages/' and are followed by one ore more digits to the `MessagePage` class.
|
270
|
+
|
209
271
|
# Watchers
|
210
272
|
PageMagic lets you set a watcher on any of the elements that you have defined on your pages. Use watchers to decide when
|
211
|
-
things have changed.
|
273
|
+
things have changed. The `watch` method can be called from anywhere within an element definition. For PageObjects it can
|
274
|
+
only be called from within hooks and helper methods.
|
212
275
|
|
213
276
|
**Note**: Watchers are not inherited
|
214
277
|
|
@@ -216,9 +279,7 @@ things have changed.
|
|
216
279
|
Method watchers watch the output of the given method name.
|
217
280
|
```ruby
|
218
281
|
button :javascript_button, css: '.fancy_button' do
|
219
|
-
|
220
|
-
watch(:url)
|
221
|
-
end
|
282
|
+
watch(:url)
|
222
283
|
|
223
284
|
after_events do
|
224
285
|
wait_until{changed?(:url)}
|
@@ -231,9 +292,7 @@ Simple watchers use the `watch` method passing two parameters, the first is the
|
|
231
292
|
eye and the second is the method that needs to be called to get the value that should be observed.
|
232
293
|
```ruby
|
233
294
|
element :product_row, css '.cta' do
|
234
|
-
|
235
|
-
element(:total, css: '.total')
|
236
|
-
end
|
295
|
+
watch(:total, :text)
|
237
296
|
|
238
297
|
after_events do
|
239
298
|
wait_until{changed?(:total)}
|
@@ -246,10 +305,8 @@ that needs to be observed. Use watch in this way if you need to do something non
|
|
246
305
|
access an element not located within the current element but elsewhere within the page.
|
247
306
|
```ruby
|
248
307
|
element :product_row, css '.cta' do
|
249
|
-
|
250
|
-
|
251
|
-
session.nav.total.text
|
252
|
-
end
|
308
|
+
watch(:total) do
|
309
|
+
session.nav.total.text
|
253
310
|
end
|
254
311
|
|
255
312
|
after_events do
|
@@ -257,15 +314,9 @@ element :product_row, css '.cta' do
|
|
257
314
|
end
|
258
315
|
end
|
259
316
|
```
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
# define what pages map to what
|
264
|
-
browser.define_page_mappings %r{/messages/\d+} => MessagePage,
|
265
|
-
'/login' => LoginPage,
|
266
|
-
'/' => MailBox
|
267
|
-
```
|
268
|
-
You can use even use regular expressions to map multiple paths to the same page. In the above example we are mapping paths that that starts with '/messages/' and are followed by one ore more digits to the `MessagePage` class.
|
317
|
+
|
318
|
+
# Waiting
|
319
|
+
It's inevitable that if there is JavaScript on the page that you are going to have to wait for things to happen before you can move on. PageMagic supplies the `wait_until` method that can be used anywhere you might need it. The wait_until method takes a block that it will execute until either that block returns true or the timeout occurs. See the method docs for details on configuring timeouts and retry intervals.
|
269
320
|
|
270
321
|
# Drivers
|
271
322
|
## Registering a custom driver
|
@@ -286,34 +337,57 @@ PageMagic.drivers.register Webkit
|
|
286
337
|
#3. Use registered driver
|
287
338
|
session = PageMagic.session(browser: webkit, url: 'https://21st-century-mail.com')
|
288
339
|
```
|
340
|
+
# Cucumber quick start
|
341
|
+
You can obviously use PageMagic anywhere you fancy but one of the places you might decide to use it is within a Cucumber test suite. If that's the case something like the following could prove useful.
|
289
342
|
|
290
|
-
|
291
|
-
|
292
|
-
You have a scenario in mind that goes something along the lines of:
|
293
|
-
- Send yourself an email with a unique subject
|
294
|
-
- Go to the Login page and login
|
295
|
-
- Find the message using it's unique subject and read it
|
296
|
-
- delete the message
|
297
|
-
|
298
|
-
You're mail client is totally 21st century so there is loads of lovely ajax etc...
|
299
|
-
|
300
|
-
Using the PageMagic you can implement an API that might look something like the following to use:
|
343
|
+
## Helper methods
|
344
|
+
Put the following in to `features/support/page_magic.rb` to make these helpers available to all of your steps.
|
301
345
|
|
302
346
|
```ruby
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
347
|
+
require 'page_magic'
|
348
|
+
require 'active_support/inflector'
|
349
|
+
require 'your_pages'
|
350
|
+
|
351
|
+
World(Module.new do
|
352
|
+
def page_class(string)
|
353
|
+
"#{string}Page".delete(' ').constantize
|
354
|
+
end
|
355
|
+
|
356
|
+
def snake_case(string)
|
357
|
+
string.delete(' ').underscore
|
358
|
+
end
|
359
|
+
|
360
|
+
def session
|
361
|
+
$session ||= begin
|
362
|
+
PageMagic.session(browser: :chrome, url: the_base_url).tap do |session|
|
363
|
+
|
364
|
+
session.define_page_mappings '/login' => LoginPage,
|
365
|
+
'/' => HomePage
|
366
|
+
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end)
|
371
|
+
```
|
372
|
+
## Example steps
|
373
|
+
Use the [above](#helper-methods) helpers to navigate to pages with steps like the following.
|
309
374
|
|
310
|
-
|
311
|
-
|
375
|
+
```ruby
|
376
|
+
Given /^I am on the '(.*)' page$/ do |page_name|
|
377
|
+
session.visit(page_class(page_name))
|
378
|
+
end
|
312
379
|
|
313
|
-
|
314
|
-
session.
|
380
|
+
And /^I set '(.*)' to be '(.*)'$/ do |field, value|
|
381
|
+
session.send(snake_case(field)).set value
|
382
|
+
end
|
315
383
|
|
316
|
-
|
384
|
+
When /^I click '(.*)'$/ do |element|
|
385
|
+
session.send(snake_case(element)).click
|
386
|
+
end
|
317
387
|
|
318
|
-
|
388
|
+
Then /^I should be on the '(.*)' page$/ do |page_name|
|
389
|
+
current_page = session.current_page.class
|
390
|
+
expected_page = page_class(page_name)
|
391
|
+
fail "On #{current_page}, expected #{expected_page}" unless current_page == expected_page
|
392
|
+
end
|
319
393
|
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module PageMagic
|
2
|
+
# for the benefit of pull review :@
|
2
3
|
class Element
|
3
4
|
# contains method for finding element definitions
|
4
5
|
module Locators
|
@@ -12,7 +13,7 @@ module PageMagic
|
|
12
13
|
def element_by_name(name, *args)
|
13
14
|
defintion = element_definitions[name]
|
14
15
|
fail ElementMissingException, (ELEMENT_NOT_DEFINED_MSG % name) unless defintion
|
15
|
-
defintion.call(*args
|
16
|
+
defintion.call(self, *args)
|
16
17
|
end
|
17
18
|
|
18
19
|
# @return [Array] class level defined element definitions
|
data/lib/page_magic/element.rb
CHANGED
@@ -12,21 +12,46 @@ module PageMagic
|
|
12
12
|
include SelectorMethods, Watchers, SessionMethods, WaitMethods, Locators
|
13
13
|
extend Elements, SelectorMethods, Forwardable
|
14
14
|
|
15
|
-
attr_reader :type, :name, :
|
15
|
+
attr_reader :type, :name, :parent_element, :browser_element, :before_events, :after_events
|
16
16
|
|
17
17
|
class << self
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
# @!method after_events
|
19
|
+
# If a block is passed in, it adds it to be run after an event is triggered on an element.
|
20
|
+
# See {EVENT_TYPES} for the
|
21
|
+
# @return [Array] all registered blocks
|
22
|
+
|
23
|
+
# @!method before_events
|
24
|
+
# If a block is passed in, it adds it to be run before an event is triggered on an element.
|
25
|
+
# @see .after_events
|
26
|
+
%i(after_events before_events).each do |method|
|
27
|
+
define_method method do |&block|
|
28
|
+
instance_variable_name = "@#{method}".to_sym
|
29
|
+
instance_variable_value = instance_variable_get(instance_variable_name) || [DEFAULT_HOOK]
|
30
|
+
instance_variable_value << block if block
|
31
|
+
instance_variable_set(instance_variable_name, instance_variable_value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get/Sets the parent element desribed by this class
|
36
|
+
# @param [Element] page_element parent page element
|
37
|
+
# @return [Element]
|
38
|
+
def parent_element(page_element = nil)
|
39
|
+
return @parent_page_element unless page_element
|
40
|
+
@parent_page_element = page_element
|
41
|
+
end
|
42
|
+
|
43
|
+
# called when class inherits this one
|
44
|
+
# @param [Class] clazz inheriting class
|
45
|
+
def inherited(clazz)
|
46
|
+
super
|
47
|
+
clazz.before_events.replace(before_events)
|
48
|
+
clazz.after_events.replace(after_events)
|
23
49
|
end
|
24
50
|
|
25
|
-
#
|
26
|
-
#
|
27
|
-
def
|
28
|
-
|
29
|
-
@before_hook = block
|
51
|
+
# Defines watchers to be used by instances
|
52
|
+
# @see Watchers#watch
|
53
|
+
def watch(name, method = nil, &block)
|
54
|
+
before_events { watch(name, method, &block) }
|
30
55
|
end
|
31
56
|
|
32
57
|
def ==(other)
|
@@ -34,11 +59,11 @@ module PageMagic
|
|
34
59
|
end
|
35
60
|
end
|
36
61
|
|
37
|
-
def initialize(browser_element
|
62
|
+
def initialize(browser_element)
|
38
63
|
@browser_element = browser_element
|
39
|
-
@
|
40
|
-
@before_events = self.class.before_events
|
41
|
-
@after_events = self.class.after_events
|
64
|
+
@parent_element = self.class.parent_element
|
65
|
+
@before_events = self.class.before_events
|
66
|
+
@after_events = self.class.after_events
|
42
67
|
@element_definitions = self.class.element_definitions.dup
|
43
68
|
wrap_events(browser_element)
|
44
69
|
end
|
@@ -64,18 +89,18 @@ module PageMagic
|
|
64
89
|
# get the current session
|
65
90
|
# @return [Session] returns the session of the parent page element.
|
66
91
|
# Capybara session
|
67
|
-
def_delegator :
|
92
|
+
def_delegator :parent_element, :session
|
68
93
|
|
69
94
|
private
|
70
95
|
|
71
|
-
def apply_hooks(raw_element:, capybara_method:,
|
96
|
+
def apply_hooks(raw_element:, capybara_method:, before_events:, after_events:)
|
72
97
|
original_method = raw_element.method(capybara_method)
|
73
98
|
this = self
|
74
99
|
|
75
100
|
raw_element.define_singleton_method(capybara_method) do |*arguments, &block|
|
76
|
-
this.instance_exec(&
|
101
|
+
before_events.each { |event| this.instance_exec(&event) }
|
77
102
|
original_method.call(*arguments, &block)
|
78
|
-
this.instance_exec(&
|
103
|
+
after_events.each { |event| this.instance_exec(&event) }
|
79
104
|
end
|
80
105
|
end
|
81
106
|
|
@@ -88,8 +113,8 @@ module PageMagic
|
|
88
113
|
next unless raw_element.respond_to?(action_method)
|
89
114
|
apply_hooks(raw_element: raw_element,
|
90
115
|
capybara_method: action_method,
|
91
|
-
|
92
|
-
|
116
|
+
before_events: before_events,
|
117
|
+
after_events: after_events)
|
93
118
|
end
|
94
119
|
end
|
95
120
|
end
|
@@ -20,7 +20,7 @@ module PageMagic
|
|
20
20
|
builder = page_element.element_by_name(method, *args)
|
21
21
|
|
22
22
|
prefecteched_element = builder.element
|
23
|
-
return builder.build(prefecteched_element
|
23
|
+
return builder.build(prefecteched_element) if prefecteched_element
|
24
24
|
|
25
25
|
elements = find(builder)
|
26
26
|
elements.size == 1 ? elements.first : elements
|
@@ -41,7 +41,7 @@ module PageMagic
|
|
41
41
|
fail ElementMissingException, ELEMENT_NOT_FOUND_MSG % query.description
|
42
42
|
end
|
43
43
|
|
44
|
-
result.to_a.collect { |e| builder.build(e
|
44
|
+
result.to_a.collect { |e| builder.build(e) }
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -23,11 +23,10 @@ module PageMagic
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Create new instance of the ElementDefinition modeled by this builder
|
26
|
-
# @param [Element] parent_page_element element containing the element modelled by this builder
|
27
26
|
# @param [Object] browser_element capybara browser element corresponding to the element modelled by this builder
|
28
27
|
# @return [Element] element definition
|
29
|
-
def build(browser_element
|
30
|
-
definition_class.new(browser_element
|
28
|
+
def build(browser_element)
|
29
|
+
definition_class.new(browser_element)
|
31
30
|
end
|
32
31
|
|
33
32
|
def ==(other)
|
data/lib/page_magic/elements.rb
CHANGED
@@ -52,16 +52,16 @@ module PageMagic
|
|
52
52
|
# @param [Hash] selector a key value pair defining the method for locating this element. See above for details
|
53
53
|
def element(*args, &block)
|
54
54
|
block ||= proc {}
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
ElementDefinitionBuilder.new(options.merge(definition_class:
|
55
|
+
options = compute_options(args.dup)
|
56
|
+
options[:type] = __callee__
|
57
|
+
section_class = options.delete(:section_class)
|
58
|
+
|
59
|
+
add_element_definition(options.delete(:name)) do |parent_element, *e_args|
|
60
|
+
definition_class = Class.new(section_class) do
|
61
|
+
parent_element(parent_element)
|
62
|
+
class_exec(*e_args, &(block))
|
63
|
+
end
|
64
|
+
ElementDefinitionBuilder.new(options.merge(definition_class: definition_class))
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -75,6 +75,15 @@ module PageMagic
|
|
75
75
|
|
76
76
|
private
|
77
77
|
|
78
|
+
def compute_options(args)
|
79
|
+
section_class = remove_argument(args, Class) || Element
|
80
|
+
{ name: compute_name(args, section_class),
|
81
|
+
selector: compute_selector(args, section_class),
|
82
|
+
options: compute_argument(args, Hash),
|
83
|
+
element: args.delete_at(0),
|
84
|
+
section_class: section_class }
|
85
|
+
end
|
86
|
+
|
78
87
|
def add_element_definition(name, &block)
|
79
88
|
fail InvalidElementNameException, 'duplicate page element defined' if element_definitions[name]
|
80
89
|
|
data/lib/page_magic/session.rb
CHANGED
@@ -24,7 +24,7 @@ module PageMagic
|
|
24
24
|
# is found then nil returned
|
25
25
|
def current_page
|
26
26
|
mapping = find_mapped_page(current_path)
|
27
|
-
@current_page = mapping
|
27
|
+
@current_page = initialize_page(mapping) if mapping
|
28
28
|
@current_page
|
29
29
|
end
|
30
30
|
|
@@ -90,7 +90,7 @@ module PageMagic
|
|
90
90
|
else
|
91
91
|
fail InvalidURLException, URL_MISSING_MSG
|
92
92
|
end
|
93
|
-
@current_page = page
|
93
|
+
@current_page = initialize_page(page) if page
|
94
94
|
self
|
95
95
|
end
|
96
96
|
|
@@ -103,6 +103,10 @@ module PageMagic
|
|
103
103
|
transitions[mapping]
|
104
104
|
end
|
105
105
|
|
106
|
+
def initialize_page(page_class)
|
107
|
+
page_class.new(self).execute_on_load
|
108
|
+
end
|
109
|
+
|
106
110
|
def matches?(string, matcher)
|
107
111
|
if matcher.is_a?(Regexp)
|
108
112
|
string =~ matcher
|
data/lib/page_magic/watchers.rb
CHANGED
@@ -25,6 +25,7 @@ module PageMagic
|
|
25
25
|
def watch(name, method = nil, &block)
|
26
26
|
fail ElementMissingException, (ELEMENT_MISSING_MSG % name) unless block || respond_to?(name)
|
27
27
|
watched_element = block ? Watcher.new(name, &block) : Watcher.new(name, method)
|
28
|
+
watchers.delete_if { |w| w.name == name }
|
28
29
|
watchers << watched_element.check(self)
|
29
30
|
end
|
30
31
|
|
data/page_magic.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: page_magic 1.0.
|
5
|
+
# stub: page_magic 1.0.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "page_magic"
|
9
|
-
s.version = "1.0.
|
9
|
+
s.version = "1.0.2"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Leon Davis"]
|
14
|
-
s.date = "2015-11-
|
14
|
+
s.date = "2015-11-16"
|
15
15
|
s.description = "Framework for modeling and interacting with webpages which wraps capybara"
|
16
16
|
s.email = "info@lad-tech.com"
|
17
17
|
s.extra_rdoc_files = [
|
data/spec/element_spec.rb
CHANGED
@@ -14,10 +14,12 @@ module PageMagic
|
|
14
14
|
|
15
15
|
let(:page) { session.current_page }
|
16
16
|
|
17
|
-
|
17
|
+
let(:described_class) do
|
18
|
+
Class.new(Element).tap { |clazz| clazz.parent_element(page) }
|
19
|
+
end
|
18
20
|
|
19
21
|
subject do
|
20
|
-
described_class.new(:page_element
|
22
|
+
described_class.new(:page_element)
|
21
23
|
end
|
22
24
|
|
23
25
|
it_behaves_like 'session accessor'
|
@@ -25,8 +27,60 @@ module PageMagic
|
|
25
27
|
it_behaves_like 'waiter'
|
26
28
|
it_behaves_like 'element locator'
|
27
29
|
|
28
|
-
describe '
|
29
|
-
|
30
|
+
describe '.after_events' do
|
31
|
+
subject do
|
32
|
+
Class.new(described_class)
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'hook set' do
|
36
|
+
it 'returns that hook' do
|
37
|
+
hook = proc {}
|
38
|
+
subject.after_events(&hook)
|
39
|
+
expect(subject.after_events).to eq([described_class::DEFAULT_HOOK, hook])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
context 'hook not registered' do
|
43
|
+
it 'returns the default hook' do
|
44
|
+
expect(subject.after_events).to eq([described_class::DEFAULT_HOOK])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '.before_events' do
|
50
|
+
subject do
|
51
|
+
Class.new(described_class)
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'hook set' do
|
55
|
+
it 'returns that hook' do
|
56
|
+
hook = proc {}
|
57
|
+
subject.before_events(&hook)
|
58
|
+
expect(subject.before_events).to eq([described_class::DEFAULT_HOOK, hook])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
context 'hook not registered' do
|
62
|
+
it 'returns the default hook' do
|
63
|
+
expect(subject.before_events).to eq([described_class::DEFAULT_HOOK])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '.inherited' do
|
69
|
+
it 'copies before hooks' do
|
70
|
+
before_hook = proc {}
|
71
|
+
described_class.before_events(&before_hook)
|
72
|
+
sub_class = Class.new(described_class)
|
73
|
+
expect(sub_class.before_events).to include(before_hook)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'copies after hooks' do
|
77
|
+
after_hook = proc {}
|
78
|
+
described_class.after_events(&after_hook)
|
79
|
+
sub_class = Class.new(described_class)
|
80
|
+
expect(sub_class.after_events).to include(after_hook)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'lets sub classes defined their own elements' do
|
30
84
|
custom_element = Class.new(described_class) do
|
31
85
|
text_field :form_field, id: 'field_id'
|
32
86
|
|
@@ -43,6 +97,18 @@ module PageMagic
|
|
43
97
|
end
|
44
98
|
end
|
45
99
|
|
100
|
+
describe '.watch' do
|
101
|
+
let(:described_class) { Class.new(Element) }
|
102
|
+
it 'adds a before hook with the watcher in it' do
|
103
|
+
described_class.watch(:object_id)
|
104
|
+
instance = described_class.new(:element)
|
105
|
+
|
106
|
+
watcher_block = instance.before_events.last
|
107
|
+
instance.instance_exec(&watcher_block)
|
108
|
+
expect(instance.watchers.first.last).to eq(instance.object_id)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
46
112
|
describe 'EVENT_TYPES' do
|
47
113
|
context 'methods created' do
|
48
114
|
it 'creates methods for each of the event types' do
|
@@ -53,7 +119,7 @@ module PageMagic
|
|
53
119
|
context 'method called' do
|
54
120
|
let(:browser_element) { instance_double(Capybara::Node::Element) }
|
55
121
|
subject do
|
56
|
-
described_class.new(browser_element
|
122
|
+
described_class.new(browser_element)
|
57
123
|
end
|
58
124
|
it 'calls the browser_element passing on all args' do
|
59
125
|
expect(browser_element).to receive(:select).with(:args)
|
@@ -63,44 +129,62 @@ module PageMagic
|
|
63
129
|
end
|
64
130
|
end
|
65
131
|
|
66
|
-
describe '#initialize' do
|
67
|
-
it 'sets the parent element' do
|
68
|
-
instance = described_class.new(page, :parent_page_element)
|
69
|
-
expect(instance.parent_page_element).to eq(:parent_page_element)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
132
|
describe 'hooks' do
|
74
133
|
subject do
|
75
134
|
Class.new(described_class) do
|
76
135
|
before_events do
|
77
|
-
|
136
|
+
call_in_before_events
|
78
137
|
end
|
79
|
-
end.new(double('button', click: true)
|
138
|
+
end.new(double('button', click: true))
|
80
139
|
end
|
81
|
-
context 'method called in
|
140
|
+
context 'method called in before_events' do
|
82
141
|
it 'calls methods on the page element' do
|
83
|
-
expect(subject).to receive(:
|
142
|
+
expect(subject).to receive(:call_in_before_events)
|
84
143
|
subject.click
|
85
144
|
end
|
86
145
|
end
|
87
146
|
|
88
|
-
context 'method called in
|
147
|
+
context 'method called in after_events' do
|
89
148
|
subject do
|
90
149
|
Class.new(described_class) do
|
91
150
|
after_events do
|
92
|
-
|
151
|
+
call_in_after_events
|
93
152
|
end
|
94
|
-
end.new(double('button', click: true)
|
153
|
+
end.new(double('button', click: true))
|
95
154
|
end
|
96
155
|
|
97
156
|
it 'calls methods on the page element' do
|
98
|
-
expect(subject).to receive(:
|
157
|
+
expect(subject).to receive(:call_in_after_events)
|
99
158
|
subject.click
|
100
159
|
end
|
101
160
|
end
|
102
161
|
end
|
103
162
|
|
163
|
+
describe '#initialize' do
|
164
|
+
it 'sets the parent element' do
|
165
|
+
instance = described_class.new(:element)
|
166
|
+
expect(instance.parent_element).to eq(page)
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'inherited items' do
|
170
|
+
let(:described_class) do
|
171
|
+
Class.new(Element)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'copies the event hooks from the class' do
|
175
|
+
before_hook = proc {}
|
176
|
+
after_hook = proc {}
|
177
|
+
described_class.before_events(&before_hook)
|
178
|
+
described_class.after_events(&after_hook)
|
179
|
+
|
180
|
+
instance = described_class.new(:element)
|
181
|
+
|
182
|
+
expect(instance.before_events).to include(before_hook)
|
183
|
+
expect(instance.after_events).to include(after_hook)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
104
188
|
describe '#method_missing' do
|
105
189
|
before do
|
106
190
|
page_class.class_eval do
|
@@ -125,7 +209,7 @@ module PageMagic
|
|
125
209
|
subject do
|
126
210
|
Class.new(described_class) do
|
127
211
|
element :sub_element, css: '.sub-element'
|
128
|
-
end.new(double(element_method: '')
|
212
|
+
end.new(double(element_method: ''))
|
129
213
|
end
|
130
214
|
it 'checks for methods on self' do
|
131
215
|
expect(subject.respond_to?(:session)).to eq(true)
|
@@ -73,7 +73,7 @@ module PageMagic
|
|
73
73
|
context 'using a block' do
|
74
74
|
it 'passes the parent element in as the last argument' do
|
75
75
|
expected_element = instance
|
76
|
-
subject.element :page_section, child_selector do |_arg1
|
76
|
+
subject.element :page_section, child_selector do |_arg1|
|
77
77
|
extend RSpec::Matchers
|
78
78
|
expect(parent_element).to eq(expected_element)
|
79
79
|
end
|
@@ -56,6 +56,16 @@ module PageMagic
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
context 'watcher with the same name added' do
|
60
|
+
it 'replaces the watcher' do
|
61
|
+
subject.watch(:object_id)
|
62
|
+
original_watcher = subject.watchers.first
|
63
|
+
subject.watch(:object_id)
|
64
|
+
expect(subject.watchers.size).to eq(1)
|
65
|
+
expect(subject.watchers.first).to_not be(original_watcher)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
59
69
|
context 'watcher defined on element that does not exist' do
|
60
70
|
it 'raises an error' do
|
61
71
|
expected_message = described_class::ELEMENT_MISSING_MSG % :missing
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: page_magic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
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-
|
11
|
+
date: 2015-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|