polonium 0.1.0

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.
Files changed (34) hide show
  1. data/CHANGES +10 -0
  2. data/README +38 -0
  3. data/Rakefile +68 -0
  4. data/lib/polonium.rb +28 -0
  5. data/lib/polonium/configuration.rb +271 -0
  6. data/lib/polonium/driver.rb +155 -0
  7. data/lib/polonium/dsl/selenium_dsl.rb +33 -0
  8. data/lib/polonium/dsl/test_unit_dsl.rb +58 -0
  9. data/lib/polonium/element.rb +207 -0
  10. data/lib/polonium/extensions/module.rb +8 -0
  11. data/lib/polonium/extensions/testrunnermediator.rb +22 -0
  12. data/lib/polonium/mongrel_selenium_server_runner.rb +37 -0
  13. data/lib/polonium/page.rb +84 -0
  14. data/lib/polonium/selenium_helper.rb +5 -0
  15. data/lib/polonium/server_runner.rb +33 -0
  16. data/lib/polonium/tasks/selenium_test_task.rb +21 -0
  17. data/lib/polonium/test_case.rb +93 -0
  18. data/lib/polonium/wait_for.rb +40 -0
  19. data/lib/polonium/webrick_selenium_server_runner.rb +33 -0
  20. data/spec/polonium/extensions/module_spec.rb +29 -0
  21. data/spec/polonium/extensions/testrunnermediator_spec.rb +19 -0
  22. data/spec/polonium/mongrel_selenium_server_runner_spec.rb +35 -0
  23. data/spec/polonium/selenium_configuration_spec.rb +359 -0
  24. data/spec/polonium/selenium_driver_spec.rb +104 -0
  25. data/spec/polonium/selenium_element_spec.rb +551 -0
  26. data/spec/polonium/selenium_page_spec.rb +249 -0
  27. data/spec/polonium/selenium_server_runner_spec.rb +42 -0
  28. data/spec/polonium/selenium_test_case_class_method_spec.rb +41 -0
  29. data/spec/polonium/selenium_test_case_spec.rb +870 -0
  30. data/spec/polonium/selenium_test_case_spec_helper.rb +16 -0
  31. data/spec/polonium/webrick_selenium_server_runner_spec.rb +117 -0
  32. data/spec/spec_helper.rb +63 -0
  33. data/spec/spec_suite.rb +6 -0
  34. metadata +82 -0
@@ -0,0 +1,33 @@
1
+ module Polonium
2
+ module SeleniumDsl
3
+ # The Configuration object.
4
+ def configuration
5
+ @configuration ||= Configuration.instance
6
+ end
7
+ attr_writer :configuration
8
+ attr_accessor :selenium_driver
9
+ include WaitFor
10
+
11
+ # Download a file from the Application Server
12
+ def download(path)
13
+ uri = URI.parse(configuration.browser_url + path)
14
+ puts "downloading #{uri.to_s}"
15
+ Net::HTTP.get(uri)
16
+ end
17
+
18
+ # Open the home page of the Application and wait for the page to load.
19
+ def open_home_page
20
+ selenium_driver.open(configuration.browser_url)
21
+ end
22
+
23
+ protected
24
+ Driver.public_instance_methods(false).each do |method_name|
25
+ delegate method_name, :to => :selenium_driver
26
+ end
27
+
28
+ def should_stop_driver?
29
+ return false unless configuration.test_browser_mode?
30
+ configuration.stop_driver?(passed?)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ module Polonium
2
+ module TestUnitDsl
3
+ include SeleniumDsl
4
+ class << self
5
+ def page_assertion(name)
6
+ module_eval(
7
+ "def assert_#{name}(value, params={})\n" +
8
+ " page.assert_#{name}(value, params)\n" +
9
+ "end",
10
+ __FILE__,
11
+ __LINE__ - 4
12
+ )
13
+ end
14
+
15
+ def element_assertion(name)
16
+ module_eval(
17
+ "def assert_#{name}(locator, *args)\n" +
18
+ " element(locator).assert_#{name}(*args)\n" +
19
+ "end",
20
+ __FILE__,
21
+ __LINE__ - 4
22
+ )
23
+ end
24
+ end
25
+
26
+ page_assertion :title
27
+ page_assertion :text_present
28
+ page_assertion :text_not_present
29
+ page_assertion :location_ends_with
30
+ deprecate :assert_location_ends_in, :assert_location_ends_with
31
+
32
+ element_assertion :value
33
+ element_assertion :attribute # yes, it's a little weird... in this case element is really an attribute
34
+ element_assertion :selected
35
+ element_assertion :checked
36
+ element_assertion :not_checked
37
+ element_assertion :text
38
+ element_assertion :element_present
39
+ element_assertion :element_not_present
40
+ element_assertion :next_sibling
41
+ element_assertion :contains_in_order
42
+ element_assertion :visible
43
+ element_assertion :not_visible
44
+
45
+ # Assert and wait for locator element to contain text.
46
+ def assert_element_contains(locator, text, options = {})
47
+ element(locator).assert_contains(text, options)
48
+ end
49
+
50
+ # Assert and wait for locator element to not contain text.
51
+ def assert_element_does_not_contain(locator, text, options={})
52
+ element(locator).assert_does_not_contain(text, options)
53
+ end
54
+ deprecate :assert_element_does_not_contain_text, :assert_element_does_not_contain
55
+ deprecate :wait_for_element_to_not_contain_text, :assert_element_does_not_contain
56
+ deprecate :wait_for_text_in_order, :assert_contains_in_order
57
+ end
58
+ end
@@ -0,0 +1,207 @@
1
+ module Polonium
2
+ class Element
3
+ include WaitFor
4
+ attr_reader :driver, :locator
5
+
6
+ def initialize(driver, locator)
7
+ @driver = driver
8
+ @locator = locator
9
+ end
10
+
11
+ def assert_element_present(params={})
12
+ driver.wait_for_is_element_present(locator, params)
13
+ end
14
+
15
+ def assert_element_not_present(params={})
16
+ driver.wait_for_is_element_not_present(locator, params)
17
+ end
18
+
19
+ def assert_value(expected_value)
20
+ assert_element_present
21
+ wait_for do |configuration|
22
+ actual_value = driver.get_value(locator)
23
+ configuration.message = "Expected '#{locator}' to be '#{expected_value}' but was '#{actual_value}'"
24
+ has_value? expected_value, actual_value
25
+ end
26
+ end
27
+
28
+ def assert_attribute(expected_value)
29
+ assert_element_present
30
+ wait_for do |configuration|
31
+ actual = driver.get_attribute(locator) #todo: actual value
32
+ configuration.message = "Expected attribute '#{locator}' to be '#{expected_value}' but was '#{actual}'"
33
+ expected_value == actual
34
+ end
35
+ end
36
+
37
+ def assert_selected(expected_value)
38
+ assert_element_present
39
+ wait_for do |configuration|
40
+ actual = driver.get_selected_label(locator)
41
+ configuration.message = "Expected '#{locator}' to be selected with '#{expected_value}' but was '#{actual}"
42
+ expected_value == actual
43
+ end
44
+ end
45
+
46
+ def assert_visible(options={})
47
+ assert_element_present
48
+ options = {
49
+ :message => "Expected '#{locator}' to be visible, but it wasn't"
50
+ }.merge(options)
51
+ wait_for(options) do
52
+ driver.is_visible(locator)
53
+ end
54
+ end
55
+
56
+ def assert_not_visible(options={})
57
+ assert_element_present
58
+ options = {
59
+ :message => "Expected '#{locator}' to be hidden, but it wasn't"
60
+ }.merge(options)
61
+ wait_for(options) do
62
+ !driver.is_visible(locator)
63
+ end
64
+ end
65
+
66
+ def assert_checked
67
+ assert_element_present
68
+ wait_for(:message => "Expected '#{locator}' to be checked") do
69
+ driver.is_checked(locator)
70
+ end
71
+ end
72
+
73
+ def assert_not_checked
74
+ assert_element_present
75
+ wait_for(:message => "Expected '#{locator}' to be checked") do
76
+ !driver.is_checked(locator)
77
+ end
78
+ end
79
+
80
+ def assert_text(expected_text, options={})
81
+ assert_element_present
82
+ wait_for(options) do |configuration|
83
+ actual = driver.get_text(locator)
84
+ configuration.message = "Expected text '#{expected_text}' to be full contents of #{locator} but was '#{actual}')"
85
+ expected_text == actual
86
+ end
87
+ end
88
+
89
+ def assert_contains(expected_text, options={})
90
+ return assert_contains_in_order(*expected_text) if expected_text.is_a? Array
91
+ assert_element_present
92
+ options = {
93
+ :message => "#{locator} should contain #{expected_text}"
94
+ }.merge(options)
95
+ wait_for(options) do
96
+ contains?(expected_text)
97
+ end
98
+ end
99
+
100
+ def assert_does_not_contain(expected_text, options={})
101
+ assert_element_present
102
+ wait_for(options) do
103
+ !inner_html.include?(expected_text)
104
+ end
105
+ end
106
+
107
+ def assert_next_sibling(expected_sibling_id, options = {})
108
+ assert_element_present
109
+ eval_js = "this.page().findElement('#{locator}').nextSibling.id"
110
+ wait_for(:message => "id '#{locator}' should be next to '#{expected_sibling_id}'") do
111
+ actual_sibling_id = driver.get_eval(eval_js)
112
+ expected_sibling_id == actual_sibling_id
113
+ end
114
+ end
115
+
116
+ def assert_contains_in_order(*text_fragments)
117
+ assert_element_present
118
+ wait_for do |configuration|
119
+ success = false
120
+
121
+ html = driver.get_text(locator)
122
+ results = find_text_order_error_fragments(html, text_fragments)
123
+ fragments_not_found = results[:fragments_not_found]
124
+ fragments_out_of_order = results[:fragments_out_of_order]
125
+
126
+ if !fragments_not_found.empty?
127
+ configuration.message = "Certain fragments weren't found:\n" <<
128
+ "#{fragments_not_found.join("\n")}\n" <<
129
+ "\nhtml follows:\n #{html}\n"
130
+ elsif !fragments_out_of_order.empty?
131
+ configuration.message = "Certain fragments were out of order:\n" <<
132
+ "#{fragments_out_of_order.join("\n")}\n" <<
133
+ "\nhtml follows:\n #{html}\n"
134
+ else
135
+ success = true
136
+ end
137
+
138
+ success
139
+ end
140
+ end
141
+
142
+
143
+ def is_present?
144
+ driver.is_element_present(locator)
145
+ end
146
+
147
+ def is_not_present?
148
+ !driver.is_element_present(locator)
149
+ end
150
+
151
+ def has_value?(expected_value, actual_value=driver.get_value(locator))
152
+ expected_value == actual_value
153
+ end
154
+
155
+ def inner_html
156
+ driver.get_inner_html(locator)
157
+ end
158
+
159
+ def contains?(text)
160
+ inner_html.include?(text)
161
+ end
162
+
163
+ def ==(other)
164
+ return false unless other.is_a?(Element)
165
+ return false unless self.driver == other.driver
166
+ return false unless self.locator == other.locator
167
+ true
168
+ end
169
+
170
+ protected
171
+ def method_missing(method_name, *args, &blk)
172
+ if driver.respond_to?(method_name)
173
+ driver_args = [locator] + args
174
+ driver.__send__(method_name, *driver_args, &blk)
175
+ else
176
+ super
177
+ end
178
+ end
179
+
180
+ def find_text_order_error_fragments(html, text_fragments)
181
+ fragments_not_found = []
182
+ fragments_out_of_order = []
183
+
184
+ previous_index = -1
185
+ previous_fragment = ''
186
+ text_fragments.each do |current_fragment|
187
+ current_index = html.index(current_fragment)
188
+ if current_index
189
+ if current_index < previous_index
190
+ message = "Fragment #{current_fragment} out of order:\n" <<
191
+ "\texpected '#{previous_fragment}'\n" <<
192
+ "\tto come before '#{current_fragment}'\n"
193
+ fragments_out_of_order << message
194
+ end
195
+ else
196
+ fragments_not_found << "Fragment #{current_fragment} was not found\n"
197
+ end
198
+ previous_index = current_index
199
+ previous_fragment = current_fragment
200
+ end
201
+ {
202
+ :fragments_not_found => fragments_not_found,
203
+ :fragments_out_of_order => fragments_out_of_order
204
+ }
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,8 @@
1
+ class Module
2
+ def deprecate(old_method_name, new_method_name)
3
+ define_method old_method_name do |*args|
4
+ warn "#{old_method_name} is deprecated. Use #{new_method_name} instead."
5
+ __send__(new_method_name, *args)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ class Test::Unit::UI::TestRunnerMediator
2
+ alias_method :run_suite_without_seleniumrc, :run_suite
3
+ def run_suite_with_seleniumrc
4
+ start_app_server
5
+ result = run_suite_without_seleniumrc
6
+ stop_app_server(result)
7
+ result
8
+ end
9
+ alias_method :run_suite, :run_suite_with_seleniumrc
10
+
11
+ protected
12
+ def start_app_server
13
+ @selenium_driver = Polonium::Configuration.instance
14
+ @app_runner = @selenium_driver.create_server_runner
15
+ @app_runner.start
16
+ end
17
+
18
+ def stop_app_server(result)
19
+ @app_runner.stop
20
+ @selenium_driver.stop_driver_if_necessary(result.passed?)
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ module Polonium
2
+ class MongrelSeleniumServerRunner < ServerRunner
3
+ def start
4
+ mongrel_configurator = configuration.create_mongrel_configurator
5
+ initialize_server(mongrel_configurator)
6
+
7
+ @thread_class.start do
8
+ start_server(mongrel_configurator)
9
+ end
10
+ @started = true
11
+ end
12
+
13
+ protected
14
+ def start_server(mongrel_configurator)
15
+ mongrel_configurator.run
16
+ mongrel_configurator.log "Mongrel running at #{configuration.internal_app_server_host}:#{configuration.internal_app_server_port}"
17
+ mongrel_configurator.join
18
+ end
19
+
20
+ def initialize_server(config)
21
+ configuration = self.configuration
22
+ config.listener do |*args|
23
+ mongrel = (args.first || self)
24
+ mongrel.log "Starting Rails in environment #{defaults[:environment]} ..."
25
+ mongrel.uri "/", :handler => mongrel.rails
26
+ mongrel.log "Rails loaded."
27
+
28
+ mongrel.log "Loading any Rails specific GemPlugins"
29
+ mongrel.load_plugins
30
+ configuration.app_server_initialization.call(mongrel)
31
+ end
32
+ end
33
+
34
+ def stop_server
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,84 @@
1
+ module Polonium
2
+ class Page
3
+ include WaitFor
4
+ attr_reader :driver
5
+ PAGE_LOADED_COMMAND = "this.browserbot.getDocument().body ? true : false"
6
+
7
+ def initialize(driver)
8
+ @driver = driver
9
+ end
10
+
11
+ def open(url)
12
+ driver.open(url)
13
+ end
14
+ alias_method :open_and_wait, :open
15
+
16
+ def assert_title(expected_title, params = {})
17
+ wait_for(params) do |configuration|
18
+ actual_title = title
19
+ configuration.message = "Expected title '#{expected_title}' but was '#{actual_title}'"
20
+ expected_title == actual_title
21
+ end
22
+ end
23
+ def title
24
+ driver.get_title
25
+ end
26
+
27
+ def assert_text_present(expected_text, options = {})
28
+ options = {
29
+ :message => "Expected '#{expected_text}' to be present, but it wasn't"
30
+ }.merge(options)
31
+ wait_for(options) do
32
+ is_text_present? expected_text
33
+ end
34
+ end
35
+ def is_text_present?(expected_text)
36
+ page_loaded? && driver.is_text_present(expected_text)
37
+ end
38
+
39
+ def assert_text_not_present(unexpected_text, options = {})
40
+ options = {
41
+ :message => "Expected '#{unexpected_text}' to be absent, but it wasn't"
42
+ }.merge(options)
43
+ wait_for(options) do
44
+ is_text_not_present? unexpected_text
45
+ end
46
+ end
47
+ def is_text_not_present?(unexpected_text)
48
+ page_loaded? && !driver.is_text_present(unexpected_text)
49
+ end
50
+
51
+ def page_loaded?
52
+ driver.get_eval(PAGE_LOADED_COMMAND) == true.to_s
53
+ end
54
+
55
+ def assert_location_ends_with(ends_with, options ={})
56
+ options = {
57
+ :message => "Expected '#{driver.get_location}' to end with '#{ends_with}'"
58
+ }.merge(options)
59
+ wait_for(options) do
60
+ location_ends_with? ends_with
61
+ end
62
+ end
63
+ def location_ends_with?(ends_with)
64
+ if driver.get_location =~ Regexp.new("#{Regexp.escape(ends_with)}$")
65
+ true
66
+ else
67
+ false
68
+ end
69
+ end
70
+
71
+ def ==(other)
72
+ return false unless other.is_a?(Page)
73
+ self.driver == other.driver
74
+ end
75
+
76
+ def method_missing(method_name, *args, &blk)
77
+ if driver.respond_to?(method_name)
78
+ driver.__send__(method_name, *args, &blk)
79
+ else
80
+ super
81
+ end
82
+ end
83
+ end
84
+ end