site_prism 0.9

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Copyright (c) 2011, Nathaniel Ritmeyer
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ 3. Neither the name Nathaniel Ritmeyer nor the names of contributors to
15
+ this software may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
19
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
22
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/site_prism.rb ADDED
@@ -0,0 +1,8 @@
1
+ module SitePrism
2
+
3
+ end
4
+
5
+ require 'site_prism/exceptions'
6
+ require 'site_prism/element_container'
7
+ require 'site_prism/page'
8
+ require 'site_prism/section'
@@ -0,0 +1,104 @@
1
+ # Contains methods applicable to both {SitePrism::Page}s and {SitePrism::Section}s. Note that they are mixed into the {SitePrism::Page}
2
+ # and {SitePrism::Section} classes so the methods below are used as class methods.
3
+ module SitePrism::ElementContainer
4
+
5
+ # Creates two methods; the first method has the same name as the element_name parameter and returns the capybara element
6
+ # located by the element_locator parameter when the method is called. The second method generated has a name with a format
7
+ # of: 'has_#\{element_name}?' which returns true if the element as located by the element_locator parameter exists, false
8
+ # if it doesn't
9
+ # @param [Symbol] element_name The name of the element
10
+ # @param [String] element_locator The CSS locator to find the element
11
+ # @example
12
+ # class HomePage < SitePrism::Page
13
+ # element :search_link, 'div.search > a'
14
+ # end
15
+ # home = HomePage.new
16
+ #
17
+ # #the element method created 2 methods...
18
+ # home.search_link #=> returns the capybara element located by the element_locator parameter
19
+ # home.has_search_link? #=> returns true if the capybara element as located by the element_locator exists, false if it doesn't
20
+ #
21
+ # #The has_search_link? method allows use of magic matchers in rspec/cucumber:
22
+ # home.should have_search_link
23
+ # home.should_not have_search_link
24
+ def element element_name, element_locator
25
+ create_existence_checker element_name, element_locator
26
+ define_method element_name.to_s do
27
+ find_one element_locator
28
+ end
29
+ end
30
+
31
+ # Works in the same way as {SitePrism::Page.element} in that it will generate two methods; one to check existence of
32
+ # the element (in the format 'has_#\{element_name}?'), and another to return not a single element, but an array of elements
33
+ # found by the css locator
34
+ # @param [Symbol] collection_name The name of the collection
35
+ # @param [String] collection_locator The CSS locator that returns the list of elements in the collection
36
+ # @example
37
+ # class HomePage < SitePrism::Page
38
+ # elements :app_links, '.title-links > a'
39
+ # end
40
+ # home = HomePage.new
41
+ #
42
+ # home.should have_app_links
43
+ # home.app_links #=> [#<Capybara::Element tag="a">, #<Capybara::Element tag="a">, #<Capybara::Element tag="a">]
44
+ # home.app_links.map {|link| link.text}.should == ['Finance', 'Maps', 'Blogs']
45
+ def elements collection_name, collection_locator
46
+ create_existence_checker collection_name, collection_locator
47
+ define_method collection_name.to_s do
48
+ find_all collection_locator
49
+ end
50
+ end
51
+ alias :collection :elements
52
+
53
+ # Creates a method that returns an instance of a {SitePrism::Section}. If a page contains a common section (eg: a search area) that
54
+ # appears on many pages, create a {SitePrism::Section} for it and then expose it in each {SitePrism::Page} that contains the section.
55
+ # Say a search engine website displays the search field and search button on each page and they always have the same IDs, they should
56
+ # be extracted into a {SitePrism::Section} that would look something like this:
57
+ #
58
+ # class SearchArea < SitePrism::Section
59
+ # element :search_field, '.q'
60
+ # element :search_button, '.btnK'
61
+ # end
62
+ #
63
+ # ...then that section could be added to any page as follows:
64
+ #
65
+ # class SearchPage < SitePrism::Page
66
+ # section :search_area, SearchArea, '.tsf-p'
67
+ # end
68
+ #
69
+ # class SearchResultsPage < SitePrism::Page
70
+ # section :search_again, SearchArea, '.tsf-p table'
71
+ # end
72
+ #
73
+ # The SearchArea section appears on both pages, but can be invoked by methods specific to the page (eg: 'search_area' and 'search_again')
74
+ # and the root element for the section can be different on the page (eg: '.tsf-p' and '.tsf-p table').
75
+ # @param [Symbol] the method name to be called against this page or section to return an instance of the {SitePrism::Section} class
76
+ # @param [Class] the class that models this area of the page
77
+ # @param [String] the CSS locator for the root element of the section on this page/section
78
+ def section section_name, section_class, section_locator
79
+ create_existence_checker section_name, section_locator
80
+ define_method section_name do
81
+ section_class.new find_one section_locator
82
+ end
83
+ end
84
+
85
+ # Works in the same way as {SitePrism::Page.section} but instead of it returning one section, it returns an array of them.
86
+ def sections section_collection_name, section_class, section_collection_locator
87
+ create_existence_checker section_collection_name, section_collection_locator
88
+ define_method section_collection_name do
89
+ find_all(section_collection_locator).collect do |element|
90
+ section_class.new element
91
+ end
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ # Creates a method used to check for the existence of the element whose details are passed to it
98
+ # @param
99
+ def create_existence_checker element_name, element_locator
100
+ define_method "has_#{element_name.to_s}?" do
101
+ element_exists? element_locator
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,7 @@
1
+ # SitePrism's exceptions...
2
+ module SitePrism
3
+ # Raised if you ask a page to load but it hasn't had its url set
4
+ class NoUrlForPage < StandardError; end
5
+ # Raised if you check to see if a page is displayed but it hasn't had its url matcher set
6
+ class NoUrlMatcherForPage < StandardError; end
7
+ end
@@ -0,0 +1,108 @@
1
+ module SitePrism
2
+ # Subclasses of {SitePrism::Page} represent pages in your app.
3
+ # class Home < SitePrism::Page
4
+ # end
5
+ #
6
+ # The above is an example of how to make a class representing the home page. There are a number of properties that can be
7
+ # set on a page - here is an example of a more fully spec'ed out page:
8
+ # class Home < SitePrism::Page
9
+ # set_url "/"
10
+ # set_url_matcher /\/home.htm$/
11
+ # end
12
+ class Page
13
+ include Capybara::DSL
14
+ extend ElementContainer
15
+
16
+ # Visits the url associated with this page
17
+ # @raise [SitePrism::NoUrlForPage] To load a page the url must be set using {.set_url}
18
+ def load
19
+ raise SitePrism::NoUrlForPage if url.nil?
20
+ visit url
21
+ end
22
+
23
+ # Checks to see if we're on this page or not
24
+ # @return true if the browser's current url matches the {.url_matcher} that has been set, false if it doesn't
25
+ # @raise [SitePrism::NoUrlMatcherForPage] To check whether we're on this page or not the url matcher must be set using {.set_url_matcher}
26
+ # @example
27
+ # class SearchPage < SitePrism::Page
28
+ # set_url_matcher /\/search.htm$/
29
+ # end
30
+ # search_page = SearchPage.new
31
+ # search_page.load
32
+ # puts "We're on the search page" if search_page.displayed?
33
+ # search_page.should be_displayed
34
+ def displayed?
35
+ raise SitePrism::NoUrlMatcherForPage if url_matcher.nil?
36
+ !(page.current_url =~ url_matcher).nil?
37
+ end
38
+
39
+ # Set the url associated with this page
40
+ # @param [String] page_url the portion of the url that identifies this page when appended onto Capybara's app_host. Calling {SitePrism::Page#load} causes Capybara to visit this page.
41
+ # @example
42
+ # class SearchPage < SitePrism::Page
43
+ # set_url "/search.htm"
44
+ # end
45
+ def self.set_url page_url
46
+ @url = page_url
47
+ end
48
+
49
+ # Set the url matcher associated with this page
50
+ # @param [Regexp] page_url_matcher a regular expression that when compared to the current browser url will match if we're on this page or not match if we're not on this page
51
+ # @example
52
+ # class SearchPage < SitePrism::Page
53
+ # set_url_matcher /\/search.htm$/
54
+ # end
55
+ def self.set_url_matcher page_url_matcher
56
+ @url_matcher = page_url_matcher
57
+ end
58
+
59
+ # Get the url associated with this page
60
+ # @see SitePrism::Page#url
61
+ # @return [String] the url originally set in {.set_url}
62
+ def self.url
63
+ @url
64
+ end
65
+
66
+ # Get the url matcher associated with this page
67
+ # @see SitePrism::Page#url_matcher
68
+ # @return [Regexp] the url matcher originally set in {.set_url_matcher}
69
+ def self.url_matcher
70
+ @url_matcher
71
+ end
72
+
73
+ # Get the url associated with this page
74
+ # @see SitePrism::Page.url
75
+ def url
76
+ self.class.url
77
+ end
78
+
79
+ # Get the url matcher associated with this page
80
+ # @see SitePrism::Page.url_matcher
81
+ def url_matcher
82
+ self.class.url_matcher
83
+ end
84
+
85
+ # Gets the title of the current page
86
+ # @return [String, nil] the text value of the title element within the page's head block
87
+ def title
88
+ title_selector = 'html > head > title'
89
+ using_wait_time(0) { page.find(title_selector).text if page.has_selector?(title_selector) }
90
+ end
91
+
92
+ private
93
+
94
+ # Page specific element finder
95
+ def find_one locator
96
+ find locator
97
+ end
98
+
99
+ # Page specific elements finder
100
+ def find_all locator
101
+ all locator
102
+ end
103
+
104
+ def element_exists? locator
105
+ has_selector? locator
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,25 @@
1
+ module SitePrism
2
+ class Section
3
+ extend ElementContainer
4
+
5
+ def initialize root_element
6
+ @root_element = root_element
7
+ end
8
+
9
+ private
10
+
11
+ # Section specific element finder
12
+ def find_one locator
13
+ @root_element.find locator
14
+ end
15
+
16
+ # Section specific elements finder
17
+ def find_all locator
18
+ @root_element.all locator
19
+ end
20
+
21
+ def element_exists? locator
22
+ @root_element.has_selector? locator
23
+ end
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: site_prism
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: "0.9"
6
+ platform: ruby
7
+ authors:
8
+ - Nat Ritmeyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-12-22 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capybara
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.1.1
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: none just yet...
27
+ email:
28
+ - nat@natontesting.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - lib/site_prism/element_container.rb
37
+ - lib/site_prism/exceptions.rb
38
+ - lib/site_prism/page.rb
39
+ - lib/site_prism/section.rb
40
+ - lib/site_prism.rb
41
+ - LICENSE
42
+ homepage: http://github.com/natritmeyer/site_prism
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.10
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: none just yet...
69
+ test_files: []
70
+
71
+ has_rdoc: