gless 1.0.1

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 ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rvmrc ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p194@gless"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.14.12 (stable)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
+ \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create "$environment_id" || {
31
+ echo "Failed to create RVM environment '${environment_id}'."
32
+ return 1
33
+ }
34
+ fi
data/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Gless #
2
+
3
+ A wrapper for Watir (specifically watir-webdriver, which is built on
4
+ top of selenium-webdriver) based on modelling web page and web site
5
+ structure. It's intended to make it easier to model complex
6
+ application workflow in an RSpec or Cucumber web site test suite.
7
+
8
+ This gem attempts to provide a more robust model for web application testing,
9
+ on top of Watir-WebDriver which already has significant improvements over just
10
+ Selenium or WebDriver, based on describing pages and then interacting with the
11
+ descriptions.
12
+
13
+ Feel free to contact the author at rlpowell@digitalkingdom.org
14
+
15
+ ## Overview And Motivation ##
16
+
17
+ Gless takes Watir elements and collects them into pages. It then
18
+ inserts a session layer on top of the pages. The session layer is
19
+ in charge of knowing what page the browser is on, managing
20
+ transitions, and checking that they worked. On top of this sits an
21
+ application layer, which is the code that uses Gless for its
22
+ testing.
23
+
24
+ The motivation is seperation of testing types.
25
+
26
+ At the page level, which is code provided by a user of Gless, the
27
+ code has very little error correction, and mostly consists of just
28
+ the elements themselves, but might have some light code tying
29
+ elements together. For example, a "log me in" method that simply
30
+ takes a username and password and clicks the login button, and does
31
+ no error checking at any step, would go here.
32
+
33
+ At the session level, which is part of Gless itself and if you need
34
+ more features please send me a pull request, are various functions
35
+ to do page-level error correction. The big one here is long\_wait,
36
+ which watches a page for changes and only moves on when it sees what
37
+ it expects.
38
+
39
+ At the application level, which is code provided by a user of Gless,
40
+ you can write any multi-page workflows you like, without having to
41
+ pay any real attention to what page your on in the code, except in
42
+ as much as if your interactions don't match the site workflow your
43
+ tests are likely to fail. :) For example, a method to register an
44
+ account from scratch and log in with it, which presumably involves
45
+ several site pages, would go here.
46
+
47
+ ## An Example ##
48
+
49
+ The best way to see how to use this library is to look in the
50
+ examples/ directory, but here's some stripped down examples.
51
+
52
+ A partial page definition:
53
+
54
+ ```ruby
55
+ element :home , :link , :href => "https://github.com/" , :validator => true , :click_destination => :LoginPage
56
+ element :explore , :link , :href => "https://github.com/explore" , :validator => true , :click_destination => :ExplorePage
57
+ element :search , :link , :href => "https://github.com/search" , :validator => true , :click_destination => :SearchPage
58
+
59
+ element :search_input , :text_field , :class => 'text' , :validator => true
60
+ element :search_button , :button , :text => 'Search' , :validator => true
61
+
62
+ url %r{^:base_url/search}
63
+
64
+ expected_title %r{^(Code Search · GitHub|Search · \S+ · GitHub)$}
65
+ ```
66
+
67
+ Given that definition, whenever the session code detects that it
68
+ *should* be on the search page (i.e. when the "search" element is
69
+ clicked), all of those elements will be checked for existence, the
70
+ url will be checked, and the title will be checked.
71
+
72
+ All of that is entirely automatic; the code that would trigger all
73
+ that would just be
74
+
75
+ @session.search.click
76
+
77
+ An example of page code that might use such a page definition:
78
+
79
+ ```ruby
80
+ def search_for stuff
81
+ self.search_input.set stuff
82
+ self.search_button.click
83
+ end
84
+ ```
85
+
86
+ An example of applicaiton level code that might use that page level
87
+ code (plus some other stuff not shown here):
88
+
89
+
90
+ ```ruby
91
+ def search_and_go name
92
+ @session.search.click
93
+ @session.search_for name
94
+ @session.goto_repository name
95
+ end
96
+ ```
97
+
98
+ As you can see, the application level can encode extremely
99
+ complicated actions, in this case "go to the search page, search for
100
+ a repository, and go to that repository page", in a compact way that
101
+ has a sensible abstraction pattern.
102
+
103
+ ## Writing Code Around Gless ##
104
+
105
+ ### Configuration File ###
106
+
107
+ Gless expects you to have a configuration file named
108
+ lib/config/development.yml (the word "development" there can be
109
+ altered by changing the ENVIRONMENT environment variable) under your
110
+ test application. See examples/ for a detailed example.
111
+
112
+ The parts that Gless uses directly, and hence are required:
113
+
114
+ ```yaml
115
+ :global: # This tag distinguishes the global config from the per-test configs; *do not remove*
116
+ :debug: false
117
+ :thumbnails: false # Whether to create small-ish "thumbnail" pictures on the replay page; requires the imagemagick system package and the mini_magick gem
118
+ :browser:
119
+ :type: local # Local or remote
120
+ :browser: firefox # Which browser to use
121
+ :port: 4444 # If remote, port to connect to the selenimu server, otherwise ignored
122
+ ```
123
+
124
+ ### The Pages ###
125
+
126
+ All of your site page description classes *must* be descendants of Gless::BasePage.
127
+
128
+ It is often useful to have your own base page class as well for
129
+ headers and footers and so on. See examples/ for a complete example
130
+ as usual, but here's a partial one:
131
+
132
+
133
+ ```ruby
134
+ rpowell@ut00-s00000> cat examples/test_github/lib/pages/test_github_base_page.rb
135
+ module TestGithub
136
+ class TestGithub::BasePage < Gless::BasePage
137
+
138
+ element :home , :link , :href => "https://github.com/" , :validator => true , :click_destination => :LoginPage
139
+ element :explore , :link , :href => "https://github.com/explore" , :validator => true , :click_destination => :ExplorePage
140
+ element :search , :link , :href => "https://github.com/search" , :validator => true , :click_destination => :SearchPage
141
+ element :features , :link , :href => "https://github.com/features" , :validator => true , :click_destination => :FeaturesPage
142
+ element :blog , :link , :href => "https://github.com/blog" , :validator => true , :click_destination => :BlogPage
143
+
144
+ end
145
+
146
+ class BlogPage < TestGithub::BasePage
147
+
148
+ url %r{^:base_url/blog$}
149
+
150
+ expected_title 'The Official GitHub Blog · GitHub'
151
+
152
+ # Stub page, but BasePage stuff still works
153
+
154
+ end
155
+ end
156
+ ```
157
+
158
+ ### The Application ###
159
+
160
+ Your application layer that sits on top of Gless must itself have
161
+ certain features, as other aspects of Gless do call back into the
162
+ application layer and/or make use of it. Here's some minimal
163
+ boilerplate that you should start with:
164
+
165
+ ```ruby
166
+ module TestGithub
167
+
168
+ class TestGithub::Application
169
+ include RSpec::Matchers
170
+
171
+ attr_accessor :browser
172
+ attr_accessor :session
173
+ attr_accessor :site
174
+ attr_accessor :base_url
175
+
176
+ def initialize( browser, config, logger )
177
+ @logger = logger
178
+ @browser = browser
179
+ @config = config
180
+
181
+ @session = Gless::Session.new( @browser, @config, @logger, self )
182
+
183
+ @session.should be_true
184
+ end
185
+ end
186
+ ```
187
+
188
+ ## Debugging Gless Applications/Tests ##
189
+
190
+ If your configuration file has ":debug: true", then Gless will
191
+ produce some pretty verbose logging of what it's doing.
192
+
193
+ A less crazy version is ":verbose: true".
194
+
195
+ It will also create a replay log directory which is intended to be
196
+ viewed in a browser. The directory location defaults to
197
+ ~/public_html/watir_replay/test/ ; the initialization of
198
+ Gless::Logger determines that location. Most actions that Gless
199
+ performs will cause the replay log to be updated a copy of the HTML
200
+ source as Gless/Watir/Selenium/WebDriver sees it.
201
+
202
+ If you have ":screenshots: true" (along with debugging), screenshots
203
+ will also be taken showing the visual state of the browser at the
204
+ time. This is quite slow, especially if the page is large. In
205
+ addition, if you have imagemagick installed, and the mini_magick
206
+ gem, and ":thumbnails: true", then smaller pictures will be included
207
+ on the main replay index page, rather than the full-sized ones.
208
+
209
+ ## Requirements ##
210
+
211
+ Ruby 1.9.3 is used for development of this project.
212
+
213
+ Gless expects that you're running tests under RSpec or Cucumber;
214
+ significant modification would likely be required to make it run
215
+ otherwise, as it uses RSpec's `should` extensively.
216
+
217
+ The following should be sufficient to allow all the rake tasks to
218
+ run:
219
+
220
+ gem install yard-tomdoc redcarpet watir-webdriver rspec
221
+
222
+ In addition, you'll need the mini\_magick gem and the imagemagick OS
223
+ package if you want thumbnails in the logging output.
224
+
225
+ ## Tests ##
226
+
227
+ Gless doesn't have any; if you can tell me how I should test something
228
+ like this besides "just run the sample app", please feel free to
229
+ suggest.
230
+
231
+ ## Documentation ##
232
+
233
+ Other than this readme, the internal API documentation is in YARD
234
+ markup. Various things you can do:
235
+
236
+ * `rake doc`
237
+ + generate the documentation
238
+ * `yard list` and `yard ri`
239
+ + command line access to the documentation
240
+ * `yard server`
241
+ + pretty web interface to the documentation
242
+
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ #require 'rspec/core/rake_task'
2
+ require 'yard'
3
+ require 'yard/rake/yardoc_task'
4
+ require 'rake/clean'
5
+
6
+ lib = File.expand_path('../lib/', __FILE__)
7
+
8
+ $:.unshift lib unless $:.include?(lib)
9
+
10
+ CLEAN.include('gless*.gem')
11
+ CLOBBER.include('doc/', '.yardoc')
12
+
13
+ desc "Build the gless gem."
14
+ task :build do
15
+ sh %{gem build gless.gemspec}
16
+ end
17
+
18
+ desc "Build then install the gless gem."
19
+ task :install => :build do
20
+ require 'gless'
21
+ sh %{gem install gless-#{Gless::VERSION}.gem}
22
+ end
23
+
24
+ #desc "Run specs for gless gem"
25
+ #RSpec::Core::RakeTask.new do
26
+ #end
27
+
28
+ desc "Generate yard documentation for the api"
29
+ YARD::Rake::YardocTask.new do
30
+ end
31
+
32
+ desc "Generate yard documentation for the api"
33
+ YARD::Rake::YardocTask.new :doc do
34
+ end
35
+
36
+ desc "Clean existing gems and re-install"
37
+ task :devinst do
38
+ ['clean','build','install'].each { |task| Rake::Task[task].invoke }
39
+ end
40
+
41
+ task :default => :install
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ - it would be nice to retry clicking an elements automatically if the expected
2
+ page transition doesn't occur ; have a session variable for
3
+ whether we should retry, and if we should, if .arrived? is false,
4
+ retry the last action
data/TODO-session ADDED
@@ -0,0 +1,65 @@
1
+ Some old notes about the session object; may or may not still be
2
+ relevant, likely mostly already be implemented at this point.
3
+
4
+ # session.rb
5
+ #
6
+ # Provides a proxy to the varous page model objects that are encountered in a
7
+ # session. Methods that are not specific to the session object are passed
8
+ # through to the current page model object.
9
+ #
10
+ # When the session is instantiated, the type of the session is given. This
11
+ # type determines what page model collections get loaded (ie for Cloud,
12
+ # Orchestra, a test app, or github, for example) During this initiation, the
13
+ # various page model classes of that collection are loaded and queried for what
14
+ # urls correspond to the page model.
15
+ #
16
+ # When a session object creates a page model object, it passes itself to that
17
+ # object during creation, and stores that object as the current proxy target.
18
+ #
19
+ # If a page model object performs an action that will result in a new target
20
+ # page, and its parent session object is not nil, the page model object will
21
+ # suggest to the parent session object what the following page will be -- it is
22
+ # up to the session object to validate that the target has correctly changed
23
+ # (discuss alternative thoughts?)
24
+ #
25
+ # Requirements:
26
+ # - page model classes have 'path' directive which takes one or more regular
27
+ # expressions (usually one) to specify a matching url pattern.
28
+ # - page model classes have a getter method for the path, that can be called
29
+ # by the session object
30
+ # - page model objects have a instance variable for the current session, which
31
+ # is passed in along with the url when being instantiated
32
+ # - page model objects should cause an exception if they are instantiated with
33
+ # an incompatible url (maybe? - discuss)
34
+ # - page model objects can be instantiated with no session or url (ie they are
35
+ # optional)
36
+ # - page model objects will tell their parent session object when an action
37
+ # they take takes the browser to another page, ideally with the new target page
38
+ # - session objects, when instantiated, will load all of the page model classes
39
+ # for the passed in type -- for each model loaded this way, the session model
40
+ # will interrogate it for the matching path pattern and store this for lookup
41
+ # later.
42
+ # - session class will have a minimal public methods collection, primarily
43
+ # acting as a proxy for the contained page object.
44
+ # - session objects will retain a history of proxy method calls and page
45
+ # transitions for logging/debugging purposes.
46
+ # - sessions can be told to go to a url, which will change the current page
47
+ #model object
48
+ #
49
+ # Path syntax:
50
+ #
51
+ # In the page model classes, the directive for the path is originally
52
+ # recommended to be:
53
+ # path r'/accounts/([0-9]+)/apps'
54
+ #
55
+ # However, a more natural language would be preferred, such as:
56
+ # path '/accounts/:account_id/apps'
57
+ #
58
+ # This has the ability to use the provided real path as an argument, and pull
59
+ # out and name the variable aspect of that path. This is used in sinatra and
60
+ # rails router code, so it has an established precident. The trick is to be
61
+ # able to parse that code to change it to the regular expression and variable
62
+ # list.
63
+ #
64
+ # The method provided to query the path pattern would result in the pattern
65
+ # itself, not the natural language representation.
@@ -0,0 +1,27 @@
1
+ load 'lib/startup.rb'
2
+
3
+ require 'rspec/expectations'
4
+ World(RSpec::Matchers)
5
+ World(RSpec::Expectations)
6
+
7
+ Before do
8
+ require 'gless'
9
+
10
+ # FIXME: the tag entry here will have to change for parallel runs.
11
+ @logger, @config, @browser = Gless.setup( :test )
12
+
13
+ if @config.get :global, :debug
14
+ require 'debugger'
15
+ end
16
+ end
17
+
18
+ After do |scenario|
19
+ if @config.get :global, :debug
20
+ if scenario.failed?
21
+ @logger.debug "Since you're in debug mode, and we've just failed out, here's a debugger. #1"
22
+ debugger
23
+ end
24
+ else
25
+ @browser.close
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ Given %r{^I start the application$} do
2
+ klass = @config.get :global, :site, :class
3
+ @application = Object.const_get(klass)::Application.new( @browser, @config, @logger )
4
+ @application.should be_true
5
+ end
6
+
7
+ When %r{^I fall through to the page object$} do
8
+ @application.session.features.click
9
+ end
10
+
11
+ When 'I go to the Gless repo via the search page' do
12
+ @application.goto_repository_from_anywhere 'gless', %r{^rlpowell\s*/\s*gless$}
13
+ end
14
+
15
+ When 'I poke lots of buttons' do
16
+ @application.poke_headers
17
+ end
18
+
19
+ Then 'I am on the Gless repo page' do
20
+ @application.session.arrived?.should be_true
21
+ @application.browser.url.should == 'https://github.com/rlpowell/gless'
22
+ end
23
+
24
+ Then %r{^I am on the Features page$} do
25
+ @application.browser.url.should == 'https://github.com/features/projects'
26
+ end
27
+
@@ -0,0 +1,12 @@
1
+ Feature: Test Github Searching
2
+
3
+ Scenario: Find The Gless Repo
4
+ Given I start the application
5
+ When I go to the Gless repo via the search page
6
+ Then I am on the Gless repo page
7
+
8
+ Scenario: Poke Around
9
+ Given I start the application
10
+ When I poke lots of buttons
11
+ And I fall through to the page object
12
+ Then I am on the Features page
@@ -0,0 +1,12 @@
1
+ :global: # This tag distinguishes the global config from the per-test configs; *do not remove*
2
+ :site:
3
+ :class: TestGithub
4
+ :url: https://github.com
5
+ :browser:
6
+ :type: remote # Local or remote
7
+ :browser: chrome # Which browser to use
8
+ :port: 7444 # If remote, port to connect to the selenimu server, otherwise ignored
9
+ :verbose: false # Whether to engage in more verbose/info level logging
10
+ :debug: false # Whether to engage in debug logging
11
+ :screenshots: false # Whether, if debugging is on, to create screenshots as part of the replay log
12
+ :thumbnails: false # Whether, if screenshots are on, to create small-ish "thumbnail" pictures on the replay page; requires the imagemagick system package and the mini_magick gem
@@ -0,0 +1,12 @@
1
+ :global: # This tag distinguishes the global config from the per-test configs; *do not remove*
2
+ :site:
3
+ :class: TestGithub
4
+ :url: https://github.com
5
+ :browser:
6
+ :type: local # local or remote
7
+ :browser: firefox # Which browser to use
8
+ :port: 4444 # If remote, port to connect to the selenimu server, otherwise ignored
9
+ :verbose: false # Whether to engage in more verbose/info level logging
10
+ :debug: false # Whether to engage in debug logging
11
+ :screenshots: false # Whether, if debugging is on, to create screenshots as part of the replay log
12
+ :thumbnails: false # Whether, if screenshots are on, to create small-ish "thumbnail" pictures on the replay page; requires the imagemagick system package and the mini_magick gem
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class BlogPage < TestGithub::BasePage
5
+
6
+ url %r{^:base_url/blog$}
7
+
8
+ expected_title 'The Official GitHub Blog · GitHub'
9
+
10
+ # Stub page, but BasePage stuff still works
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class ExplorePage < TestGithub::BasePage
5
+
6
+ url %r{^:base_url/explore$}
7
+
8
+ expected_title 'Explore · GitHub'
9
+
10
+ # Stub page, but BasePage stuff still works
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class FeaturesPage < TestGithub::BasePage
5
+
6
+ url %r{^:base_url/features/projects$}
7
+
8
+ expected_title 'Features / Project Management · GitHub'
9
+
10
+ # Stub page, but BasePage stuff still works
11
+
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class LoginPage < TestGithub::BasePage
5
+
6
+ url %r{^:base_url/?$}
7
+
8
+ set_entry_url ':base_url'
9
+
10
+ expected_title 'GitHub · Build software better, together.'
11
+
12
+ # Stub page, but BasePage stuff still works
13
+
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class RepoPage < TestGithub::BasePage
5
+
6
+ # Not much of a restriction
7
+ url %r{^:base_url}
8
+
9
+ expected_title %r{^\S+ · GitHub$}
10
+
11
+ # Stub page, but BasePage stuff still works
12
+
13
+ end
14
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ module TestGithub
4
+ class SearchPage < TestGithub::BasePage
5
+
6
+ element :search_input , :text_field , :class => 'text' , :validator => true
7
+ element :search_button , :button , :text => 'Search' , :validator => true
8
+
9
+ url %r{^:base_url/search}
10
+
11
+ expected_title %r{^(Code Search · GitHub|Search · \S+ · GitHub)$}
12
+
13
+ def search_for stuff
14
+ self.search_input.set stuff
15
+ self.search_button.click
16
+ end
17
+
18
+ def goto_repository name
19
+ @session.log.debug "SearchPage: goto_repository: name: #{name}"
20
+ (find_repository name)[:link].click
21
+ @session.acceptable_pages = TestGithub::RepoPage
22
+ end
23
+
24
+ def find_repository name
25
+ @session.log.debug "SearchPage: find_repository: name: #{name}"
26
+ if name.is_a?(Regexp)
27
+ key = repositories.keys.find { |key| key =~ name }
28
+ elsif name.is_a?(String)
29
+ key = name
30
+ end
31
+
32
+ @session.log.debug "SearchPage: find_repository: key: #{key}"
33
+
34
+ repositories[key]
35
+ end
36
+
37
+ def repositories
38
+ repos = self.divs.select { |div| div.class_name == 'result' }
39
+
40
+ @session.log.debug "SearchPage: repositories: repos: #{repos.inspect}"
41
+
42
+ repositories = Hash.new
43
+ i = 0
44
+ repos.each do |repo|
45
+ link = repo.h2.a
46
+ data = Hash.new
47
+ data[:index] = i
48
+ data[:link] = link
49
+ data[:url] = link.href
50
+ data[:name] = link.text
51
+ repositories[link.text] = data
52
+ i += 1
53
+ end
54
+
55
+ @session.log.debug "SearchPage: repositories: final: #{repositories.inspect}"
56
+
57
+ repositories
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ module TestGithub
2
+ class TestGithub::BasePage < Gless::BasePage
3
+
4
+ element :home , :link , :href => "https://github.com/" , :validator => true , :click_destination => :LoginPage
5
+ element :explore , :link , :href => "https://github.com/explore" , :validator => true , :click_destination => :ExplorePage
6
+ element :search , :link , :href => "https://github.com/search" , :validator => true , :click_destination => :SearchPage
7
+ element :features , :link , :href => "https://github.com/features" , :validator => true , :click_destination => :FeaturesPage
8
+ element :blog , :link , :href => "https://github.com/blog" , :validator => true , :click_destination => :BlogPage
9
+
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ $: << File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'yaml'
6
+ require 'watir-webdriver'
7
+
8
+ require 'gless'
9
+
10
+ Gless::EnvConfig.env_dir = File.dirname(__FILE__)
11
+
12
+ require 'pages/test_github_base_page'
13
+ Dir["#{File.dirname(__FILE__)}/pages/*/*_page.rb"].each {|r| load r }
14
+ Dir["#{File.dirname(__FILE__)}/pages/*_page.rb"].each {|r| load r }
15
+
16
+ require 'test_github'