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 CHANGED
@@ -6,3 +6,4 @@ pkg/*
6
6
  *.iml
7
7
  *.ipr
8
8
  *.iws
9
+ doc/
@@ -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
+
@@ -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
- @page_data["url"] ? page.visit(@page_data["url"]) : raise("url not defined for page")
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
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module PageObject
3
- VERSION = "0.1.1"
3
+ VERSION = "0.1.2"
4
4
  end
5
5
  end
@@ -0,0 +1,12 @@
1
+ module MonkeyPatch
2
+ module Hash
3
+ def symbolize_keys!
4
+ keys.each do |key|
5
+ self[(key.to_sym rescue key) || key] = delete(key)
6
+ end
7
+ self
8
+ end
9
+ end
10
+ end
11
+
12
+ Hash.send(:include, MonkeyPatch::Hash)
@@ -63,8 +63,9 @@ describe "Page" do
63
63
  capybara_page.should have_content "Email Address"
64
64
  end
65
65
 
66
- it "should fail if url is not specified" do
67
- expect { page_object({}).visit }.to raise_error(Exception, "url not defined for page")
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.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: &2156144500 !ruby/object:Gem::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: *2156144500
24
+ version_requirements: *2161878000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mocha
27
- requirement: &2156141140 !ruby/object:Gem::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: *2156141140
35
+ version_requirements: *2161877580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sinatra
38
- requirement: &2156139320 !ruby/object:Gem::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: *2156139320
46
+ version_requirements: *2161877060
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: capybara
49
- requirement: &2156062360 !ruby/object:Gem::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: *2156062360
57
+ version_requirements: *2161876640
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: capybara
60
- requirement: &2156061060 !ruby/object:Gem::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: *2156061060
68
+ version_requirements: *2161876080
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-expectations
71
- requirement: &2156059420 !ruby/object:Gem::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: *2156059420
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