capybara-pageobject 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|