capybara-pageobject 0.1.1 → 0.1.2
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/.gitignore +1 -0
- data/README.rdoc +112 -0
- data/lib/capybara-pageobject.rb +2 -0
- data/lib/capybara-pageobject/page.rb +9 -2
- data/lib/capybara-pageobject/url_parser.rb +26 -0
- data/lib/capybara-pageobject/version.rb +1 -1
- data/lib/monkey-patch/hash.rb +12 -0
- data/spec/page_spec.rb +17 -2
- data/spec/support/test_website.rb +5 -0
- data/spec/url_parser_spec.rb +39 -0
- metadata +18 -13
data/.gitignore
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
= Capybara-PageObject
|
2
|
+
|
3
|
+
capybara-pageobject helps you easily define page objects for capybara based tests.
|
4
|
+
Page objects allow you to abstract your tests from low-level UI bindings.
|
5
|
+
This allows you to easily adapt your tests to UI changes.
|
6
|
+
|
7
|
+
== Setup
|
8
|
+
|
9
|
+
Install as a gem:
|
10
|
+
|
11
|
+
sudo gem install capybara-pageobject
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
Add the following section to your env.rb or acceptance_helper:
|
16
|
+
|
17
|
+
Capybara::PageObject.configure do |config|
|
18
|
+
config.page_file = 'support/pages/pages.yml'
|
19
|
+
end
|
20
|
+
|
21
|
+
The gem makes a method 'website' available to your tests.
|
22
|
+
|
23
|
+
|
24
|
+
== Page definitions
|
25
|
+
|
26
|
+
Page definitions are specified in a YAML file. for eg:
|
27
|
+
|
28
|
+
home_page:
|
29
|
+
id: "#header_banner"
|
30
|
+
url: "/"
|
31
|
+
login_form:
|
32
|
+
id: "#login-form"
|
33
|
+
url: "/sign_in"
|
34
|
+
attributes:
|
35
|
+
email_address: "#email"
|
36
|
+
password: "#password.red"
|
37
|
+
error_message: "#alert_message"
|
38
|
+
actions:
|
39
|
+
login_button: "#login_submit"
|
40
|
+
|
41
|
+
=== page
|
42
|
+
Each first-level definition specifies a page.
|
43
|
+
The above YAML declares that you have two pages home_page and login_form.
|
44
|
+
|
45
|
+
=== url
|
46
|
+
The url attribute specifies the url of the page.
|
47
|
+
You can navigate to these pages as below:
|
48
|
+
|
49
|
+
website.home_page.visit
|
50
|
+
website.login_form.visit
|
51
|
+
|
52
|
+
=== Dynamic urls
|
53
|
+
For RESTful dynamci urls, use the following definition:
|
54
|
+
comment_page:
|
55
|
+
url: "/users/:user_id/comments/:comment_id"
|
56
|
+
|
57
|
+
You can then visit the comments page as below:
|
58
|
+
|
59
|
+
website.comments_page.visit user_id: 3, comment_id: 1
|
60
|
+
|
61
|
+
=== id
|
62
|
+
The id attribute specifies the CSS3 selector which uniquely identifies that the page is loaded.
|
63
|
+
You can use this as below:
|
64
|
+
|
65
|
+
website.login_form.visit
|
66
|
+
website.login_form.should be_visible
|
67
|
+
|
68
|
+
=== attributes
|
69
|
+
Each attribute on the page is specified alongwith the CSS3 selector to uniquely identify it.
|
70
|
+
Each attribute definition can be used as below:
|
71
|
+
|
72
|
+
website.login_form.email_address "foo bar" #Set email address to 'foo bar'
|
73
|
+
website.login_form.some_checkbox true #Check checkbox
|
74
|
+
website.login_form.email_address.should == "foo bar" #Assert email address is equal to 'foo bar'
|
75
|
+
website.login_form.email_address.should be_visible #Assert email address is visible
|
76
|
+
|
77
|
+
Attributes also work with text content. for eg:
|
78
|
+
|
79
|
+
website.login_form.error_message.should == "Some error occurred"
|
80
|
+
|
81
|
+
=== actions
|
82
|
+
Any clickable (button or link) element on the page is defined as an action.
|
83
|
+
Each action definition can be used as below:
|
84
|
+
|
85
|
+
website.login_form.login_button.click
|
86
|
+
website.login_form.login_button.should be_disabled
|
87
|
+
website.login_form.login_button.should be_visible
|
88
|
+
|
89
|
+
==Page block mode
|
90
|
+
To make your tests more readable, you can specify page interactions within a block. for eg:
|
91
|
+
|
92
|
+
website.login_form do
|
93
|
+
email_address 'foo@example.com'
|
94
|
+
password 'testing'
|
95
|
+
login_button.click
|
96
|
+
error_message.should be_visible
|
97
|
+
end
|
98
|
+
|
99
|
+
===Custom Page Class
|
100
|
+
If you need to define custom actions on the page, add a class which extends Capybara::PageObject::Page
|
101
|
+
You can them specify it in the YAML file as below:
|
102
|
+
|
103
|
+
login_form:
|
104
|
+
id: "#login-form"
|
105
|
+
url: "/sign_in"
|
106
|
+
class: CustomLoginForm
|
107
|
+
|
108
|
+
===TODO
|
109
|
+
* XPath selectors
|
110
|
+
* Standard setters ie website.login_form.email_address = "foo bar"
|
111
|
+
|
112
|
+
|
data/lib/capybara-pageobject.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require "capybara-pageobject/version"
|
2
2
|
require "monkey-patch/string"
|
3
3
|
require "monkey-patch/object"
|
4
|
+
require "monkey-patch/hash"
|
4
5
|
|
5
6
|
module Capybara
|
6
7
|
module PageObject
|
8
|
+
autoload :UrlParser, 'capybara-pageobject/url_parser'
|
7
9
|
autoload :Page, 'capybara-pageobject/page'
|
8
10
|
autoload :CapybaraHelper, 'capybara-pageobject/capybara_helper'
|
9
11
|
autoload :Element, 'capybara-pageobject/element'
|
@@ -1,8 +1,11 @@
|
|
1
|
+
require 'capybara/rspec/matchers'
|
2
|
+
|
1
3
|
module Capybara
|
2
4
|
module PageObject
|
3
5
|
class Page
|
4
6
|
include CapybaraHelper
|
5
7
|
include RSpec::Matchers
|
8
|
+
include Capybara::RSpecMatchers
|
6
9
|
|
7
10
|
attr_accessor :context
|
8
11
|
|
@@ -20,14 +23,18 @@ module Capybara
|
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
def visit
|
24
|
-
|
26
|
+
def visit url_params={}
|
27
|
+
page.visit(UrlParser.new(@page_data["url"]).format(url_params))
|
25
28
|
end
|
26
29
|
|
27
30
|
def visible?
|
28
31
|
@page_data["id"] ? if_absent(false) { page.find(@page_data["id"]).visible? } : raise("id not defined for page")
|
29
32
|
end
|
30
33
|
|
34
|
+
def has_content? content
|
35
|
+
page.has_content?(content.to_s)
|
36
|
+
end
|
37
|
+
|
31
38
|
def page_title
|
32
39
|
if_absent("") { page.find("head title").text }
|
33
40
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Capybara
|
2
|
+
module PageObject
|
3
|
+
class UrlParser
|
4
|
+
|
5
|
+
def initialize url
|
6
|
+
raise 'url is not defined' if url.blank?
|
7
|
+
@url = url.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def format url_params
|
11
|
+
url_params.symbolize_keys!
|
12
|
+
dynamic_params = parse_params(@url)
|
13
|
+
|
14
|
+
raise "Please pass url parameters: #{dynamic_params}" unless url_params.keys.sort == dynamic_params.sort
|
15
|
+
url_params.each_pair { |param, value| @url.gsub!(":#{param}", value.to_s) }
|
16
|
+
@url
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def parse_params url
|
22
|
+
url.scan(/:(\w+)/).flatten.map { |p| p.to_sym }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/page_spec.rb
CHANGED
@@ -63,8 +63,9 @@ describe "Page" do
|
|
63
63
|
capybara_page.should have_content "Email Address"
|
64
64
|
end
|
65
65
|
|
66
|
-
it "should
|
67
|
-
|
66
|
+
it "should visit pages with dynamic urls" do
|
67
|
+
page_object({"url" => "/users/:user_id/comments/:id"}).visit(user_id: 3, id: 2)
|
68
|
+
capybara_page.should have_content "User data"
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
@@ -86,6 +87,20 @@ describe "Page" do
|
|
86
87
|
end
|
87
88
|
end
|
88
89
|
|
90
|
+
describe "has_content?" do
|
91
|
+
before(:each) do
|
92
|
+
@page = page_object({"url" => "/form"})
|
93
|
+
@page.visit
|
94
|
+
end
|
95
|
+
it "should return true if content is present" do
|
96
|
+
@page.should have_content "led zeppelin"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should handle dates" do
|
100
|
+
@page.should have_content Date.parse("1983-01-01")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
89
104
|
describe "page_title" do
|
90
105
|
it "should return page title if page has title in head" do
|
91
106
|
page = page_object({"url" => "/form"})
|
@@ -24,10 +24,15 @@ class TestWebsite < Sinatra::Base
|
|
24
24
|
'<div id="foo1">led zeppelin</div><div id="foo2">the doors</div>'
|
25
25
|
end
|
26
26
|
|
27
|
+
get '/users/3/comments/2' do
|
28
|
+
'<div id="user_home">User data</div>'
|
29
|
+
end
|
30
|
+
|
27
31
|
get '/form' do
|
28
32
|
page_with do
|
29
33
|
<<-FORM
|
30
34
|
<div id="attr1">led zeppelin</div>
|
35
|
+
<div>1983-01-01</div>
|
31
36
|
<div id="hidden_attr" style="display:none">the doors</div>
|
32
37
|
<form id="unique_form">
|
33
38
|
<input type="text" id="field1" value="Creedence Rlearwater Revival"/>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "UrlParser" do
|
4
|
+
describe "format" do
|
5
|
+
it "should return url if it is static" do
|
6
|
+
Capybara::PageObject::UrlParser.new("/users/1").format({}).should == "/users/1"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should duplicate url string" do
|
10
|
+
url = "/users/:user_id"
|
11
|
+
parser = Capybara::PageObject::UrlParser.new(url)
|
12
|
+
parser.format(user_id: 2)
|
13
|
+
url.should == "/users/:user_id"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise error if dynamic url is called without params" do
|
17
|
+
expect { Capybara::PageObject::UrlParser.new("/users/:id").format({}) }.to raise_error(Exception, 'Please pass url parameters: [:id]')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise error if number of parameters does not match" do
|
21
|
+
expect { Capybara::PageObject::UrlParser.new("/users/:user_id/actions/:id").format({id: 1}) }.to raise_error(Exception, 'Please pass url parameters: [:user_id, :id]')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise error if parameter names don't match" do
|
25
|
+
expect { Capybara::PageObject::UrlParser.new("/users/:user_id").format({id: 1}) }.to raise_error(Exception, 'Please pass url parameters: [:user_id]')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should substitute url parameters" do
|
29
|
+
Capybara::PageObject::UrlParser.new("/users/:id").format({id: 2}).should == "/users/2"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should substitute multiple url parameters and ignore order" do
|
33
|
+
Capybara::PageObject::UrlParser.new("/users/:user_id/actions/:id").format({id: 2, user_id: 3}).should == "/users/3/actions/2"
|
34
|
+
end
|
35
|
+
|
36
|
+
it { expect { Capybara::PageObject::UrlParser.new(nil) }.to raise_error(Exception, 'url is not defined') }
|
37
|
+
it { expect { Capybara::PageObject::UrlParser.new("") }.to raise_error(Exception, 'url is not defined') }
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-pageobject
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-02-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2161878000 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2161878000
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mocha
|
27
|
-
requirement: &
|
27
|
+
requirement: &2161877580 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2161877580
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sinatra
|
38
|
-
requirement: &
|
38
|
+
requirement: &2161877060 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.9.4
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2161877060
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: capybara
|
49
|
-
requirement: &
|
49
|
+
requirement: &2161876640 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2161876640
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: capybara
|
60
|
-
requirement: &
|
60
|
+
requirement: &2161876080 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.0.0
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2161876080
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec-expectations
|
71
|
-
requirement: &
|
71
|
+
requirement: &2161875660 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2161875660
|
80
80
|
description: Introduce page objects to your capybara-based functional tests
|
81
81
|
email:
|
82
82
|
- deepak.lewis@gmail.com
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- .gitignore
|
88
88
|
- .rvmrc
|
89
89
|
- Gemfile
|
90
|
+
- README.rdoc
|
90
91
|
- Rakefile
|
91
92
|
- capybara-pageobject.gemspec
|
92
93
|
- lib/capybara-pageobject.rb
|
@@ -95,8 +96,10 @@ files:
|
|
95
96
|
- lib/capybara-pageobject/capybara_helper.rb
|
96
97
|
- lib/capybara-pageobject/element.rb
|
97
98
|
- lib/capybara-pageobject/page.rb
|
99
|
+
- lib/capybara-pageobject/url_parser.rb
|
98
100
|
- lib/capybara-pageobject/version.rb
|
99
101
|
- lib/capybara-pageobject/website.rb
|
102
|
+
- lib/monkey-patch/hash.rb
|
100
103
|
- lib/monkey-patch/object.rb
|
101
104
|
- lib/monkey-patch/string.rb
|
102
105
|
- spec/action_spec.rb
|
@@ -108,6 +111,7 @@ files:
|
|
108
111
|
- spec/support/matchers/delegate.rb
|
109
112
|
- spec/support/pages/pages.yml
|
110
113
|
- spec/support/test_website.rb
|
114
|
+
- spec/url_parser_spec.rb
|
111
115
|
- spec/website_spec.rb
|
112
116
|
homepage: ''
|
113
117
|
licenses: []
|
@@ -143,4 +147,5 @@ test_files:
|
|
143
147
|
- spec/support/matchers/delegate.rb
|
144
148
|
- spec/support/pages/pages.yml
|
145
149
|
- spec/support/test_website.rb
|
150
|
+
- spec/url_parser_spec.rb
|
146
151
|
- spec/website_spec.rb
|