terminus_spec 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.gitignore +26 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +7 -0
  6. data/HISTORY.md +54 -0
  7. data/LICENSE +20 -0
  8. data/README.md +13 -0
  9. data/Rakefile +43 -0
  10. data/cucumber.yml +6 -0
  11. data/lib/terminus_spec.rb +200 -0
  12. data/lib/terminus_spec/factory.rb +27 -0
  13. data/lib/terminus_spec/generators.rb +80 -0
  14. data/lib/terminus_spec/locators.rb +23 -0
  15. data/lib/terminus_spec/logger.rb +7 -0
  16. data/lib/terminus_spec/matchers.rb +41 -0
  17. data/lib/terminus_spec/platform_selenium.rb +18 -0
  18. data/lib/terminus_spec/platform_selenium/platform_object.rb +214 -0
  19. data/lib/terminus_spec/platform_selenium/web_objects/all.rb +98 -0
  20. data/lib/terminus_spec/platform_selenium/web_objects/button.rb +13 -0
  21. data/lib/terminus_spec/platform_selenium/web_objects/link.rb +13 -0
  22. data/lib/terminus_spec/platform_selenium/web_objects/text_field.rb +14 -0
  23. data/lib/terminus_spec/platform_watir.rb +18 -0
  24. data/lib/terminus_spec/platform_watir/platform_object.rb +190 -0
  25. data/lib/terminus_spec/platform_watir/web_objects/all.rb +88 -0
  26. data/lib/terminus_spec/platform_watir/web_objects/text_field.rb +13 -0
  27. data/lib/terminus_spec/platforms.rb +25 -0
  28. data/lib/terminus_spec/version.rb +3 -0
  29. data/lib/terminus_spec/web_objects/all.rb +172 -0
  30. data/lib/terminus_spec/web_objects/button.rb +32 -0
  31. data/lib/terminus_spec/web_objects/link.rb +40 -0
  32. data/lib/terminus_spec/web_objects/text_field.rb +45 -0
  33. data/spec/spec_helper.rb +37 -0
  34. data/spec/terminus_spec/factory_spec.rb +40 -0
  35. data/spec/terminus_spec/generators_spec.rb +179 -0
  36. data/spec/terminus_spec/locators_spec.rb +30 -0
  37. data/spec/terminus_spec/platform_selenium_spec.rb +28 -0
  38. data/spec/terminus_spec/platform_watir_spec.rb +32 -0
  39. data/spec/terminus_spec/platforms_spec.rb +43 -0
  40. data/spec/terminus_spec/terminus_spec.rb +271 -0
  41. data/spec/terminus_spec/web_objects/all_spec.rb +87 -0
  42. data/spec/terminus_spec/web_objects/button_spec.rb +35 -0
  43. data/spec/terminus_spec/web_objects/link_spec.rb +46 -0
  44. data/spec/terminus_spec/web_objects/text_field_spec.rb +48 -0
  45. data/spec/terminus_spec/webobject_selenium_spec.rb +154 -0
  46. data/spec/terminus_spec/webobject_watir_spec.rb +120 -0
  47. data/specs/app/favicon.ico +0 -0
  48. data/specs/app/images/mass_extinction.jpg +0 -0
  49. data/specs/app/index.html +20 -0
  50. data/specs/app/modal_1.html +41 -0
  51. data/specs/app/modal_2.html +29 -0
  52. data/specs/app/server.rb +25 -0
  53. data/specs/app/style.css +18 -0
  54. data/specs/app/success_1.html +12 -0
  55. data/specs/app/success_2.html +12 -0
  56. data/specs/app/test_event.html +39 -0
  57. data/specs/app/test_form.html +114 -0
  58. data/specs/app/test_frame.html +15 -0
  59. data/specs/app/test_iframe.html +15 -0
  60. data/specs/app/test_static.html +92 -0
  61. data/specs/engine/borg.rb +27 -0
  62. data/specs/engine/hooks.rb +23 -0
  63. data/terminus_spec.gemspec +31 -0
  64. metadata +198 -0
@@ -0,0 +1,26 @@
1
+ *.gem
2
+ .bundle/*
3
+ Gemfile.lock
4
+ pkg/*
5
+ chromedriver.log
6
+ results.html
7
+
8
+ # subversion
9
+ .svn/*
10
+
11
+ # scov/rcov generated
12
+ coverage/*
13
+
14
+ # komodo
15
+ *.komodoproject
16
+ .komodotools/*
17
+
18
+ # rubymine
19
+ .idea/*
20
+
21
+ # linux swap files
22
+ *.swp
23
+ *.swo
24
+
25
+ # mac file finder
26
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm_install_on_use_flag=1
2
+ rvm --create use ruby-1.9.2@terminus_spec
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 1.9.2
3
+
4
+ notifications:
5
+ recipients:
6
+ - jeffnyman@gmail.com
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Adding rake so travis-ci will build and run tests properly.
4
+ gem 'rake'
5
+
6
+ # Specify your gem's dependencies in terminus_spec.gemspec
7
+ gemspec
@@ -0,0 +1,54 @@
1
+ Change Log and History
2
+ ======================
3
+
4
+ ## Version 0.1.0 / 2011-11-11
5
+
6
+ Alpha phase. TermniusSpec can be bundled up as a gem.
7
+
8
+ * Browser-Level Actions Supported:
9
+ * title
10
+ * text
11
+ * html
12
+ * current url
13
+ * refresh
14
+ * back
15
+ * forward
16
+ * clear cookies
17
+ * save screenshot
18
+ * navigate to
19
+ * will alert (handles alert message boxes)
20
+ * will prompt (handles prompt message boxes)
21
+ * will confirm (handles confirmation message boxes)
22
+ * attach to window
23
+
24
+ * Web Objects Supported:
25
+ * links
26
+ * text fields
27
+ * buttons
28
+
29
+ * Timing Elements Supported:
30
+ * wait until
31
+ * when present
32
+ * when exists
33
+ * when visible
34
+ * when not visible
35
+
36
+
37
+ ## Version 0.0.4 / 2011-11-10
38
+
39
+ Getting ready for an alpha phase. The basic structure of platform objects, web objects, generators, and locators has been put in place. RSpec tests are running. Cucumber framework was put in place and found to be working. Sample application has been updated to allow for more specific testing and the Cucumber framework is being started over.
40
+
41
+
42
+ ## Version 0.0.3 / 2011-11-08
43
+
44
+ Generated the framework that will allow TerminusSpec to be tested both via RSpec and Cucumber. The Cucumber testing has been designed to match the structure of how exectuable specifications will be used with Terminus as an application. The PlatformObject concept was put in place.
45
+
46
+
47
+ ## Version 0.0.2 / 2011-11-07
48
+
49
+ Added a test application as part of the framework. This included adding in a sample test project. This will not only show how Cucumber should be used with Terminus but also give a way to test the application at a system level.
50
+
51
+
52
+ ## Version 0.0.1 / 2011-11-07
53
+
54
+ Initial creation of the gem framework.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Jeff Nyman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # TerminusSpec [![Build Status](https://secure.travis-ci.org/jnyman/terminus_spec.png)](http://travis-ci.org/jnyman/terminus_spec)
2
+
3
+ This gem is designed to provide a testing framework for creating executable test specifications.
4
+
5
+
6
+ ## Credits
7
+
8
+ Thanks to Jeff Morgan (http://www.cheezyworld.com/) for his page-object gem and Alister Scott (http://watirmelon.com) for his watir-page-helper gem. I learned a lot from analyzing their code and working to craft my own solution around theirs. Rather than fork their projects, my changes were systemic enough to warrant creating a new project.
9
+
10
+
11
+ ## Copyright
12
+
13
+ Copyright (c) 2011 Jeff Nyman. See LICENSE for details.
@@ -0,0 +1,43 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'cucumber/rake/task'
4
+
5
+ server_process = nil
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.ruby_opts = "-I lib:spec"
9
+ spec.pattern = 'spec/**/*_spec.rb'
10
+ end
11
+ task :spec
12
+
13
+ task :start_server do
14
+ root = Dir.pwd
15
+ Dir.chdir(Dir.pwd + '/specs/app/')
16
+ server_process = IO.popen('ruby server.rb')
17
+ Dir.chdir(root)
18
+ end
19
+
20
+ task :stop_server do
21
+ IO.popen("taskkill /pid #{server_process.pid} /f /t > NUL 2>&1")
22
+ end
23
+
24
+ namespace :specs do
25
+
26
+ Cucumber::Rake::Task.new(:watir_webdriver, "Run specs with Watir") do |config|
27
+ config.profile = 'watir'
28
+ end
29
+
30
+ Cucumber::Rake::Task.new(:selenium_webdriver, "Run specs with Selenium") do |config|
31
+ config.profile = 'selenium'
32
+ end
33
+
34
+ desc 'Run all Cucumber specs'
35
+ task :all => [:watir_webdriver, :selenium_webdriver]
36
+ task :watir => [:start_server, :watir_webdriver, :stop_server]
37
+ task :selenium => [:start_server, :selenium_webdriver, :stop_server]
38
+ end
39
+
40
+ desc 'Run all RSpec and Cucumber tests'
41
+ task :test => ['spec', 'specs:all']
42
+
43
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ default: DRIVER=watir BROWSER=firefox -r specs/engine/borg.rb -r specs specs
2
+
3
+ watir: DRIVER=watir BROWSER=firefox --no-source --color --format pretty --tags ~@selenium -r specs/engine/borg.rb -r specs specs
4
+ selenium: DRIVER=selenium BROWSER=firefox --no-source --color --format pretty --tags ~@watir -r specs/engine/borg.rb -r specs specs
5
+
6
+ # --format html -o results.html
@@ -0,0 +1,200 @@
1
+ require 'terminus_spec/version'
2
+ require 'terminus_spec/logger'
3
+ require 'terminus_spec/matchers'
4
+ require 'terminus_spec/platforms'
5
+ require 'terminus_spec/generators'
6
+ require 'terminus_spec/locators'
7
+
8
+ module TerminusSpec
9
+ include Matchers
10
+ include Platforms
11
+ include Locators
12
+
13
+ # @return [Watir::Browser] the platform browser
14
+ # @return [Selenium::WebDriver::Driver] the platform browser
15
+ attr_reader :browser
16
+
17
+ # @return [TerminusSpec::Platforms::WatirWebDriver::PlatformObject] the platform object
18
+ # @return [TerminusSpec::Platforms::SeleniumWebDriver::PlatformObject] the platform object
19
+ attr_reader :platform
20
+
21
+ # This makes sure that any page classes that include TerminusSpec will be
22
+ # given access to the generator methods based on web objects that are
23
+ # declared in the page class.
24
+ def self.included(caller)
25
+ caller.extend TerminusSpec::Generators
26
+ end
27
+
28
+ # Creates a platform object.
29
+ # @param [Watir::Browser or Selenium::WebDriver::Driver] the platform browser to use
30
+ def initialize(browser, visit=nil)
31
+ @browser = browser
32
+ establish_platform_driver_for browser
33
+ setup_page if respond_to?(:setup_page)
34
+ goto if visit && respond_to?(:goto)
35
+ end
36
+
37
+ # Navigate to the specified URL. The URL can be specified as a domain
38
+ # address or as a file-based link.
39
+ # @param [String] the full URL to navigate to
40
+ def navigate_to(url)
41
+ @platform.navigate_to url
42
+ end
43
+
44
+ # Returns the text of the current page.
45
+ def text
46
+ @platform.text
47
+ end
48
+
49
+ # Returns the title of the current page as displayed in the browser.
50
+ def title
51
+ @platform.title
52
+ end
53
+
54
+ # Returns the html of the current page
55
+ def html
56
+ @platform.html
57
+ end
58
+
59
+ # Returns the current page URL.
60
+ def current_url
61
+ @platform.current_url
62
+ end
63
+
64
+ # Refreshes the current page.
65
+ def refresh
66
+ @platform.refresh
67
+ end
68
+
69
+ # Goes back to the preceding page in history.
70
+ def back
71
+ @platform.back
72
+ end
73
+
74
+ # Goes forward to the succeeding page in history.
75
+ def forward
76
+ @platform.forward
77
+ end
78
+
79
+ # Clears the cookies from the browser.
80
+ def clear_cookies
81
+ @platform.clear_cookies
82
+ end
83
+
84
+ # Saves the current screenshot to a provided URL. The file
85
+ # will be saved as a PNG file.
86
+ def save_screenshot(file_name)
87
+ @platform.save_screenshot file_name
88
+ end
89
+
90
+ # Waits until a condition is found to be true or a timeout occurs.
91
+ #
92
+ # @param [Numeric] the amount of time to wait for the condition to return true.
93
+ # @param [String] the message to include with the error if the timeout duration is exceeded.
94
+ # @param block the logic to execute.
95
+ #
96
+ # @example
97
+ # page.wait_until(3, 'Record Saved message was not found.') do
98
+ # page.text.should match(/^Record Saved$/)
99
+ # end
100
+ def wait_until(timeout=15, message=nil, &block)
101
+ @platform.wait_until(timeout, message, &block)
102
+ end
103
+
104
+ # Captures the execution of an alert popup.
105
+ #
106
+ # @param block the action that will cause the alert to display
107
+ # @return [String] the message that was contained in the alert
108
+ #
109
+ # @example
110
+ # message = page.will_alert do
111
+ # page.submit
112
+ # end
113
+ def will_alert(&block)
114
+ @platform.will_alert(&block)
115
+ end
116
+
117
+ # Captures the execution of a confirmation popup.
118
+ #
119
+ # @param [bool] what response you want to return back from the confirmation popup
120
+ # @param block the action that will cause the confirmation to display
121
+ # @return [String] the message that was prompted in the confirmation
122
+ #
123
+ # @example
124
+ # message = page.will_confirm(true) do
125
+ # page.submit
126
+ # end
127
+ def will_confirm(response, &block)
128
+ @platform.will_confirm(response, &block)
129
+ end
130
+
131
+ # Captures the execution of a prompt popup.
132
+ #
133
+ # @param [string] the user entered value that is returned from the prompt
134
+ # @param block the action that will cause the prompt to display
135
+ # @return [Hash] A has containing two keys. :message contains the prompt message and
136
+ # :default_value contains the default value for the prompt if provided
137
+ #
138
+ # @example
139
+ # message = page.will_prompt("Question") do
140
+ # page.submit
141
+ # end
142
+ def will_prompt(response, &block)
143
+ @platform.will_prompt(response, &block)
144
+ end
145
+
146
+ # Attaches to a displayed window. The window can be located using either the
147
+ # title attribute of the window or a direct URL. The URL does not have to be
148
+ # the entire URL; it can just be a page name (like index.html). Since
149
+ # attaching to a window can be problematic due to race conditions, a second
150
+ # try will be attempted if any exceptions occur.
151
+ #
152
+ # @param [Hash] either :title or :url of the window.
153
+ # @param block any code that should be executed before actions taken on the
154
+ # window that is being attached to
155
+ #
156
+ # @example
157
+ # page.attach_to_window(:title => "Display Results")
158
+ # page.attach_to_window(:url => results.html)
159
+ def attach_to_window(identifier, &block)
160
+ begin
161
+ @platform.attach_to_window(identifier, &block)
162
+ rescue
163
+ sleep 2
164
+ @platform.attach_to_window(identifier, &block)
165
+ end
166
+ end
167
+
168
+ # Captures the execution of a model dialog opens that dialog as a window.
169
+ # The new window can then be attached to.
170
+ #
171
+ # @param block the action that will cause the modal dialog
172
+ #
173
+ # @example
174
+ # page.will_be_modal do
175
+ # page.submit
176
+ # end
177
+ def will_be_modal(&block)
178
+ script =
179
+ %Q{
180
+ window.showModalDialog = function(sURL, vArguments, sFeatures) {
181
+ window.dialogArguments = vArguments;
182
+ modalWin = window.open(sURL, 'modal', sFeatures);
183
+ return modalWin;
184
+ }
185
+ }
186
+ browser.execute_script script
187
+ yield if block_given?
188
+ end
189
+
190
+ private
191
+
192
+ def establish_platform_driver_for(browser)
193
+ @platform = platform_for browser, TerminusSpec::Platforms.list
194
+ end
195
+
196
+ def process_block(&block)
197
+ block.arity == 1 ? block.call(self) : self.instance_eval(&block)
198
+ end
199
+
200
+ end
@@ -0,0 +1,27 @@
1
+ module TerminusSpec
2
+ module Factory
3
+
4
+ # This is the method that visits a page object after it has been created.
5
+ #
6
+ # @param [PageClass] a class that has included the TerminusSpec module
7
+ # @param [block] an optional set of logic to be called on the page object
8
+ # @return [PageObject] a page object
9
+ def visit(page_class, &block)
10
+ on page_class, true, &block
11
+ end
12
+
13
+ # This is the method that creates a page object.
14
+ #
15
+ # @param [PageClass] a class that has included the TerminusSpec module
16
+ # @param [Boolean] a boolean indicating if the page should be visited after
17
+ # it is created
18
+ # @param [block] an optional set of logic to be called on the page object
19
+ # @return [PageObject] a page object
20
+ def on(page_class, visit=false, &block)
21
+ @page = page_class.new(@browser, visit)
22
+ block.call @page if block
23
+ @page
24
+ end
25
+
26
+ end # module Factory
27
+ end # module TerminusSpec
@@ -0,0 +1,80 @@
1
+ module TerminusSpec
2
+ module Generators
3
+
4
+ # Allows you to specify a direct URL as part of a page object.
5
+ # @param [String] the url for the page.
6
+ def url_is(url)
7
+ define_method("goto") do
8
+ @platform.navigate_to url
9
+ end
10
+ end
11
+
12
+ # Create methods to do the following:
13
+ # Select a link object.
14
+ # Return a link object.
15
+ # @param [String] identifier how a link will be referred to
16
+ # @param [Hash] locator how a link will be recognized
17
+ # @param optional block to be invoked when object method is called
18
+ def link(identifier, locator=nil, &block)
19
+ define_method(identifier) do
20
+ return @platform.click_link_for locator.clone unless block_given?
21
+ self.send("#{identifier}_object").click
22
+ end
23
+
24
+ define_method("#{identifier}_object") do
25
+ return process_block(&block) if block_given?
26
+ @platform.get_link_for locator.clone
27
+ end
28
+
29
+ alias_method "#{identifier}_link".to_sym, "#{identifier}_object".to_sym
30
+ end
31
+
32
+ # Creates methods to do the following:
33
+ # Enter text into a text field object
34
+ # Get the text that is in a text field object
35
+ # Return a text field object.
36
+ # @param [String] name how a text field will be referred to
37
+ # @param [Hash] identifier how a text field will be recognized
38
+ # @param optional block to be invoked when object method is called
39
+ def text_field(identifier, locator=nil, &block)
40
+ define_method(identifier) do
41
+ return @platform.get_text_field_value_for locator.clone unless block_given?
42
+ self.send("#{identifier}_object").value
43
+ end
44
+
45
+ define_method("#{identifier}=") do |value|
46
+ return @platform.set_text_field_value_for(locator.clone, value) unless block_given?
47
+ self.send("{identifier}_object").value = value
48
+ end
49
+
50
+ define_method("#{identifier}_object") do
51
+ return process_block(&block) if block_given?
52
+ @platform.get_text_field_for locator.clone
53
+ end
54
+
55
+ alias_method "#{identifier}_text_field".to_sym, "#{identifier}_object".to_sym
56
+ end
57
+
58
+
59
+ # Creates methods to do the following:
60
+ # Click a button object.
61
+ # Return a button object.
62
+ # @param [String] name how a button will be referred to
63
+ # @param [Hash] identifier how a button will be recognized
64
+ # @param optional block to be invoked when object method is called
65
+ def button(identifier, locator=nil, &block)
66
+ define_method(identifier) do
67
+ return @platform.click_button_for locator.clone unless block_given?
68
+ self.send("#{identifer}_object").click
69
+ end
70
+
71
+ define_method("#{identifier}_object") do
72
+ return process_block(&block) if block_given?
73
+ @platform.get_button_for locator.clone
74
+ end
75
+
76
+ alias_method "#{identifier}_button".to_sym, "#{identifier}_object".to_sym
77
+ end
78
+
79
+ end # module Generators
80
+ end # module TerminusSpec