rubidium 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Gemfile +16 -0
- data/LICENSE +20 -0
- data/README +8 -0
- data/README.rdoc +18 -0
- data/VERSION +1 -0
- data/bin/rubidium +54 -0
- data/examples/google.com/googleSuite.html +14 -0
- data/examples/google.com/sanityTest.html +58 -0
- data/init.rb +29 -0
- data/lib/rubidium.rb +9 -0
- data/lib/rubidium/converter.rb +25 -0
- data/lib/rubidium/spec_writer.rb +75 -0
- data/lib/rubidium/test_case.rb +26 -0
- data/lib/rubidium/test_suite.rb +24 -0
- data/lib/rubidium/translator.rb +242 -0
- data/rakefile.rb +68 -0
- data/rubidium.gemspec +90 -0
- data/spec/rubidium/google.com/sanity_test_spec.rb +29 -0
- data/spec/rubidium_spec.rb +22 -0
- data/spec/spec_helper.rb +8 -0
- data/templates/rakefile.rb.erb +56 -0
- data/templates/spec.rb.erb +23 -0
- data/templates/spec_helper.rb.erb +100 -0
- data/todo.org +0 -0
- metadata +152 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# disable_system_gems
|
2
|
+
clear_sources
|
3
|
+
source 'http://gemcutter.org'
|
4
|
+
source 'http://gems.github.com'
|
5
|
+
source 'http://gems.rubyforge.org'
|
6
|
+
|
7
|
+
gem "rake"
|
8
|
+
gem "selenium-client", "1.2.7", :require_as => 'selenium/client'
|
9
|
+
gem "nokogiri", ">= 1.4.0"
|
10
|
+
#gem "jeweler"
|
11
|
+
|
12
|
+
gem "rspec", "1.1.8", :require_as => 'spec', :only => :never
|
13
|
+
gem "deep_test", "1.2.2"
|
14
|
+
gem "ruby-debug"
|
15
|
+
gem "syntax"
|
16
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Incite
|
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.
|
data/README
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= rubidium
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2009 davidlee. See LICENSE for details.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/rubidium
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require File.join(File.dirname(__FILE__), '../init')
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
|
7
|
+
optparse = OptionParser.new do |opts|
|
8
|
+
|
9
|
+
# Set a banner, displayed at the top
|
10
|
+
# of the help screen.
|
11
|
+
opts.banner = "Usage: rubidium [options] source_folder destination_folder"
|
12
|
+
|
13
|
+
opts.separator ""
|
14
|
+
opts.separator "Specific options:"
|
15
|
+
|
16
|
+
# Define the options, and what they do
|
17
|
+
options[:verbose] = false
|
18
|
+
opts.on( '-v', '--verbose', 'Output more information' ) do
|
19
|
+
options[:verbose] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
# This displays the help screen, all programs are
|
23
|
+
# assumed to have this option.
|
24
|
+
opts.on( '-h', '--help', 'You\'re looking at it' ) do
|
25
|
+
puts opts
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
# Mandatory argument.
|
30
|
+
opts.on("-i", "--input FOLDER",
|
31
|
+
"Find and convert all test suites in FOLDER") do |src|
|
32
|
+
options[:source] << src
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-o", "--output FOLDER",
|
36
|
+
"Find and convert all test suites in FOLDER") do |dest|
|
37
|
+
options[:destination] << dest
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
optparse.parse!
|
43
|
+
|
44
|
+
p options
|
45
|
+
p ARGV
|
46
|
+
|
47
|
+
options[:source] ||= ARGV.shift
|
48
|
+
options[:destination] ||= ARGV.shift
|
49
|
+
|
50
|
+
if options[:source] && options[:destination]
|
51
|
+
Rubidium::Converter.new(options[:source]).write!(options[:destination])
|
52
|
+
end
|
53
|
+
|
54
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
|
6
|
+
<title>Test Suite</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1" class="selenium"><tbody>
|
10
|
+
<tr><td><b>Test Suite</b></td></tr>
|
11
|
+
<tr><td><a href="sanityTest.html">sanityTest</a></td></tr>
|
12
|
+
</tbody></table>
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,58 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
6
|
+
<link rel="selenium.base" href="http://www.google.com.au/" />
|
7
|
+
<title>sanityTest</title>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<table cellpadding="1" cellspacing="1" border="1">
|
11
|
+
<thead>
|
12
|
+
<tr><td rowspan="1" colspan="3">sanityTest</td></tr>
|
13
|
+
</thead><tbody>
|
14
|
+
<!--testing google loads-->
|
15
|
+
<tr>
|
16
|
+
<td>open</td>
|
17
|
+
<td>/</td>
|
18
|
+
<td></td>
|
19
|
+
</tr>
|
20
|
+
<tr>
|
21
|
+
<td>assertTextPresent</td>
|
22
|
+
<td>Google</td>
|
23
|
+
<td></td>
|
24
|
+
</tr>
|
25
|
+
<tr>
|
26
|
+
<td>assertTextNotPresent</td>
|
27
|
+
<td>Bing</td>
|
28
|
+
<td></td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<td>type</td>
|
32
|
+
<td>q</td>
|
33
|
+
<td>wikipedia</td>
|
34
|
+
</tr>
|
35
|
+
<tr>
|
36
|
+
<td>keyPress</td>
|
37
|
+
<td>q</td>
|
38
|
+
<td>\13</td>
|
39
|
+
</tr>
|
40
|
+
<tr>
|
41
|
+
<td>waitForElementPresent</td>
|
42
|
+
<td>css=a.l</td>
|
43
|
+
<td></td>
|
44
|
+
</tr>
|
45
|
+
<tr>
|
46
|
+
<td>verifyTextPresent</td>
|
47
|
+
<td>Wikipedia, the free encyclopedia</td>
|
48
|
+
<td></td>
|
49
|
+
</tr>
|
50
|
+
<tr>
|
51
|
+
<td>assertElementPresent</td>
|
52
|
+
<td>link=Wikipedia, the free encyclopedia</td>
|
53
|
+
<td></td>
|
54
|
+
</tr>
|
55
|
+
|
56
|
+
</tbody></table>
|
57
|
+
</body>
|
58
|
+
</html>
|
data/init.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
def f(relpath)
|
2
|
+
root_path = File.dirname(__FILE__)
|
3
|
+
File.expand_path(File.join(root_path, relpath))
|
4
|
+
end
|
5
|
+
|
6
|
+
begin
|
7
|
+
|
8
|
+
# require f 'vendor/gems/environment'
|
9
|
+
# Bundler.require_env
|
10
|
+
# rescue LoadError
|
11
|
+
# puts "ack! run gem bundle"
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
gem "rake", ">= 0.8.7"
|
15
|
+
gem "selenium-client", "= 1.2.7"
|
16
|
+
gem "nokogiri", ">= 1.4.0"
|
17
|
+
gem "rspec", "= 1.1.8"
|
18
|
+
gem "deep_test", "= 1.2.2"
|
19
|
+
gem "ruby-debug", "> 0"
|
20
|
+
require 'rake'
|
21
|
+
require 'nokogiri'
|
22
|
+
require 'spec'
|
23
|
+
require 'deep_test'
|
24
|
+
require 'ruby-debug'
|
25
|
+
require 'selenium/client'
|
26
|
+
|
27
|
+
require f 'lib/rubidium'
|
28
|
+
end
|
29
|
+
|
data/lib/rubidium.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Rubidium
|
4
|
+
class Converter
|
5
|
+
|
6
|
+
attr_reader :test_suites
|
7
|
+
|
8
|
+
# given a source directory, find all test suites in it, and prepare ruby translations of them.
|
9
|
+
def initialize(source_folder)
|
10
|
+
raise ArgumentError.new("source folder expected") unless File.directory?(source_folder)
|
11
|
+
|
12
|
+
@test_suites = `grep -rnl suiteTable #{source_folder}`.split("\n").map do |fn|
|
13
|
+
TestSuite.new(fn)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# write the ruby tests to the given output folder
|
18
|
+
def write!(output_folder)
|
19
|
+
FileUtils.mkdir_p output_folder unless File.directory?(output_folder)
|
20
|
+
SpecWriter.new(output_folder).write!(@test_suites)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Rubidium
|
5
|
+
class SpecWriter
|
6
|
+
|
7
|
+
def initialize(output_folder)
|
8
|
+
@output_folder = output_folder
|
9
|
+
end
|
10
|
+
|
11
|
+
def write!(*tests)
|
12
|
+
tests.flatten!
|
13
|
+
process_rakefile
|
14
|
+
process_helper
|
15
|
+
test_suites, test_cases = tests.partition { |t| t.is_a?(Rubidium::TestSuite) }
|
16
|
+
process_test_suites test_suites
|
17
|
+
process_test_cases test_cases
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def process_rakefile
|
23
|
+
template_path = f 'templates/rakefile.rb.erb'
|
24
|
+
output_path = File.join(@output_folder, "rakefile.rb")
|
25
|
+
process_template(template_path, output_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_helper
|
29
|
+
template_path = f 'templates/spec_helper.rb.erb'
|
30
|
+
output_path = File.join(@output_folder, "spec_helper.rb")
|
31
|
+
process_template(template_path, output_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_test_suites(test_suites)
|
35
|
+
template_path = f 'templates/spec.rb.erb'
|
36
|
+
test_suites.each do |ts|
|
37
|
+
ts.test_cases.each do |tc|
|
38
|
+
output_folder = File.join(@output_folder, underscore(ts.name))
|
39
|
+
output_path = File.join(output_folder, "#{underscore tc.name}_spec.rb")
|
40
|
+
FileUtils.mkdir_p(output_folder)
|
41
|
+
process_template(template_path, output_path) do
|
42
|
+
@application_url = tc.base_url unless tc.base_url == ""
|
43
|
+
@test_case = tc
|
44
|
+
@test_suite = ts
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def underscore string
|
51
|
+
string.gsub(/ /,'_')
|
52
|
+
end
|
53
|
+
|
54
|
+
def process_test_cases(test_cases)
|
55
|
+
test_cases.each do |tc|
|
56
|
+
template_path = f 'templates/spec.erb'
|
57
|
+
output_path = File.join(@output_folder, "#{tc.name}_spec.rb")
|
58
|
+
process_template(template_path, output_path) do
|
59
|
+
@test_case = tc
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def process_template(template_path, output_path, &block)
|
65
|
+
if File.exists?(output_path)
|
66
|
+
FileUtils.rm(output_path)
|
67
|
+
end
|
68
|
+
File.open(output_path, 'w') do |fh|
|
69
|
+
yield if block_given?
|
70
|
+
fh.write ERB.new(File.read(template_path)).result(binding)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rubidium
|
2
|
+
class TestCase
|
3
|
+
attr_reader :title, :base_url, :selenese, :path
|
4
|
+
alias_method :table, :selenese
|
5
|
+
alias_method :name, :title
|
6
|
+
|
7
|
+
def initialize(path)
|
8
|
+
@path = path
|
9
|
+
x = Nokogiri::HTML(File.read(path))
|
10
|
+
@title = x.xpath('//title').first.text
|
11
|
+
@base_url = x.xpath('//link').attr('href').value
|
12
|
+
@selenese = x.xpath('//tbody/tr').map do |tr|
|
13
|
+
tr.search('td').map(&:text).reject { |txt| txt == "" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def ruby
|
18
|
+
Translator.translate(selenese)
|
19
|
+
end
|
20
|
+
|
21
|
+
def commands
|
22
|
+
Translator.translate(selenese)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rubidium
|
2
|
+
class TestSuite
|
3
|
+
attr_reader :path, :title, :test_case_paths, :test_cases
|
4
|
+
alias_method :name, :title
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
@test_cases = []
|
9
|
+
x = Nokogiri::HTML(File.read(path))
|
10
|
+
@title = x.xpath('//title').text
|
11
|
+
return false unless x.search('html').attribute 'xmlns' # filter out test reports
|
12
|
+
@test_case_paths = x.xpath('//table/tbody/tr/td/a').map {|a| test_case_path a.attributes['href'].text }
|
13
|
+
@test_cases = @test_case_paths.map { |p| Rubidium::TestCase.new(p) }
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def test_case_path relpath
|
19
|
+
dir = File.dirname(path)
|
20
|
+
File.expand_path(File.join(dir, relpath))
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
module Rubidium
|
2
|
+
|
3
|
+
# these commands accept an assert | verify | waitFor prefix
|
4
|
+
|
5
|
+
VARIANTS = {
|
6
|
+
'Alert' => [:pattern],
|
7
|
+
'AlertNotPresent' => [],
|
8
|
+
'AlertPresent' => [],
|
9
|
+
'AllButtons' => [:pattern],
|
10
|
+
'AllFields' => [:pattern],
|
11
|
+
'AllLinks' => [:pattern],
|
12
|
+
'AllWindowIds' => [:pattern],
|
13
|
+
'AllWindowNames' => [:pattern],
|
14
|
+
'AllWindowTitles' => [:pattern],
|
15
|
+
'Attribute' => [:attributeLocator, :pattern],
|
16
|
+
'AttributeFromAllWindows' => [:attributeName, :pattern],
|
17
|
+
'BodyText' => [:pattern],
|
18
|
+
'Checked' => [:locator],
|
19
|
+
'Confirmation' => [:pattern],
|
20
|
+
'ConfirmationNotPresent' => [],
|
21
|
+
'ConfirmationPresent' => [],
|
22
|
+
'Cookie' => [:pattern],
|
23
|
+
'CookieByName' => [:name, :pattern],
|
24
|
+
'CookieNotPresent' => [:name],
|
25
|
+
'CookiePresent' => [:name],
|
26
|
+
'CursorPosition' => [:locator, :pattern],
|
27
|
+
'Editable' => [:locator],
|
28
|
+
'ElementHeight' => [:locator, :pattern],
|
29
|
+
'ElementIndex' => [:locator, :pattern],
|
30
|
+
'ElementNotPresent' => [:locator],
|
31
|
+
'ElementPositionLeft' => [:locator, :pattern],
|
32
|
+
'ElementPositionTop' => [:locator, :pattern],
|
33
|
+
'ElementPresent' => [:locator],
|
34
|
+
'ElementWidth' => [:locator, :pattern],
|
35
|
+
'Eval' => [:script, :pattern],
|
36
|
+
'Expression' => [:expression, :pattern],
|
37
|
+
'HtmlSource' => [:pattern],
|
38
|
+
'Location' => [:pattern],
|
39
|
+
'MouseSpeed' => [:pattern],
|
40
|
+
'NotAlert' => [:pattern],
|
41
|
+
'NotAllButtons' => [:pattern],
|
42
|
+
'NotAllFields' => [:pattern],
|
43
|
+
'NotAllLinks' => [:pattern],
|
44
|
+
'NotAllWindowIds' => [:pattern],
|
45
|
+
'NotAllWindowNames' => [:pattern],
|
46
|
+
'NotAllWindowTitles' => [:pattern],
|
47
|
+
'NotAttribute' => [:attributeLocator, :pattern],
|
48
|
+
'NotAttributeFromAllWindows' => [:attributeName, :pattern],
|
49
|
+
'NotBodyText' => [:pattern],
|
50
|
+
'NotChecked' => [:locator],
|
51
|
+
'NotConfirmation' => [:pattern],
|
52
|
+
'NotCookie' => [:pattern],
|
53
|
+
'NotCookieByName' => [:name, :pattern],
|
54
|
+
'NotCursorPosition' => [:locator, :pattern],
|
55
|
+
'NotEditable' => [:locator],
|
56
|
+
'NotElementHeight' => [:locator, :pattern],
|
57
|
+
'NotElementIndex' => [:locator, :pattern],
|
58
|
+
'NotElementPositionLeft' => [:locator, :pattern],
|
59
|
+
'NotElementPositionTop' => [:locator, :pattern],
|
60
|
+
'NotElementWidth' => [:locator, :pattern],
|
61
|
+
'NotErrorOnNext' => [:message],
|
62
|
+
'NotEval' => [:script, :pattern],
|
63
|
+
'NotExpression' => [:expression, :pattern],
|
64
|
+
'NotFailureOnNext' => [:message],
|
65
|
+
'NotHtmlSource' => [:pattern],
|
66
|
+
'NotLocation' => [:pattern],
|
67
|
+
'NotMouseSpeed' => [:pattern],
|
68
|
+
'NotOrdered' => [:locator, :locator],
|
69
|
+
'NotPrompt' => [:pattern],
|
70
|
+
'NotSelectOptions' => [:selectLocator, :pattern],
|
71
|
+
'NotSelected' => [:selectLocator, :optionLocator],
|
72
|
+
'NotSelectedId' => [:selectLocator, :pattern],
|
73
|
+
'NotSelectedIds' => [:selectLocator, :pattern],
|
74
|
+
'NotSelectedIndex' => [:selectLocator, :pattern],
|
75
|
+
'NotSelectedIndexes' => [:selectLocator, :pattern],
|
76
|
+
'NotSelectedLabel' => [:selectLocator, :pattern],
|
77
|
+
'NotSelectedLabels' => [:selectLocator, :pattern],
|
78
|
+
'NotSelectedValue' => [:selectLocator, :pattern],
|
79
|
+
'NotSelectedValues' => [:selectLocator, :pattern],
|
80
|
+
'NotSomethingSelected' => [:selectLocator],
|
81
|
+
'NotSpeed' => [:pattern],
|
82
|
+
'NotTable' => [:tableCellAddress, :pattern],
|
83
|
+
'NotText' => [:locator, :pattern],
|
84
|
+
'NotTitle' => [:pattern],
|
85
|
+
'NotValue' => [:locator, :pattern],
|
86
|
+
'NotVisible' => [:locator],
|
87
|
+
'NotWhetherThisFrameMatchFrameExpression' => [:currentFrameString, :target],
|
88
|
+
'NotWhetherThisWindowMatchWindowExpression' => [:currentWindowString, :target],
|
89
|
+
'NotXpathCount' => [:xpath, :pattern],
|
90
|
+
'Ordered' => [:locator1, :locator2],
|
91
|
+
'Prompt' => [:pattern],
|
92
|
+
'PromptNotPresent' => [],
|
93
|
+
'PromptPresent' => [],
|
94
|
+
'SelectOptions' => [:selectLocator, :pattern],
|
95
|
+
'SelectedId' => [:selectLocator, :pattern],
|
96
|
+
'SelectedIds' => [:selectLocator, :pattern],
|
97
|
+
'SelectedIndex' => [:selectLocator, :pattern],
|
98
|
+
'SelectedIndexes' => [:selectLocator, :pattern],
|
99
|
+
'SelectedLabel' => [:selectLocator, :pattern],
|
100
|
+
'SelectedLabels' => [:selectLocator, :pattern],
|
101
|
+
'SelectedValue' => [:selectLocator, :pattern],
|
102
|
+
'SelectedValues' => [:selectLocator, :pattern],
|
103
|
+
'SomethingSelected' => [:selectLocator],
|
104
|
+
'Speed' => [:pattern],
|
105
|
+
'Table' => [:tableCellAddress, :pattern],
|
106
|
+
'Text' => [:locator, :pattern],
|
107
|
+
'TextNotPresent' => [:pattern],
|
108
|
+
'TextPresent' => [:pattern],
|
109
|
+
'Title' => [:pattern],
|
110
|
+
'Value' => [:locator, :pattern],
|
111
|
+
'Visible' => [:locator],
|
112
|
+
'WhetherThisFrameMatchFrameExpression' => [:currentFrameString, :target],
|
113
|
+
'WhetherThisWindowMatchWindowExpression' => [:currentWindowString, :target],
|
114
|
+
'XpathCount' => [:xpath, :pattern],
|
115
|
+
}
|
116
|
+
|
117
|
+
class Translator
|
118
|
+
COMPOSITE = /^(assert|verify|waitFor)([a-zA-Z]+)$/
|
119
|
+
PATTERN = /^(regexpi?|exact|glob):/
|
120
|
+
def self.translate(selenese)
|
121
|
+
selenese.map { |row| translate_command(*row) }
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
# A "Pattern" in selenium nomenclature is a string matcher.
|
127
|
+
# The default is a glob (? and * expansion).
|
128
|
+
|
129
|
+
def self.pattern(string)
|
130
|
+
# string =~ PATTERN
|
131
|
+
string.gsub! PATTERN, ''
|
132
|
+
type = $1 || 'glob'
|
133
|
+
send("#{type}_pattern", string)
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.glob_pattern(string)
|
137
|
+
if string =~ /\?|\*/
|
138
|
+
string = Regexp.escape(string)
|
139
|
+
string.gsub! /\\\?/, '.'
|
140
|
+
string.gsub! /\\\*/, '.*'
|
141
|
+
Regexp.new(string)
|
142
|
+
else
|
143
|
+
string
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.exact_pattern(string)
|
148
|
+
string
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.regexp_pattern(string)
|
152
|
+
/#{string}/
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.regexpi_pattern(string)
|
156
|
+
/#{string}/i
|
157
|
+
end
|
158
|
+
|
159
|
+
protected
|
160
|
+
|
161
|
+
def self.default_timeout
|
162
|
+
10000
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.build_composite_command(command, target=nil, value=nil)
|
166
|
+
# p [:build, command, target, value]
|
167
|
+
command =~ COMPOSITE
|
168
|
+
verb = $1
|
169
|
+
variant = $2
|
170
|
+
expectation = variant.gsub!(/Not/, '') ? 'should_not' : 'should'
|
171
|
+
ruby_command = ['', 'get_', 'is_'].map {|s| s + underscore(variant) }.detect { |s| client.respond_to?(s) }
|
172
|
+
ruby_args = []
|
173
|
+
args = [target, value].compact
|
174
|
+
client.method(ruby_command).arity.times do
|
175
|
+
ruby_args << args.shift
|
176
|
+
end
|
177
|
+
ruby_args = ruby_args.compact.map(&:inspect).join(", ")
|
178
|
+
|
179
|
+
result = args.first ? pattern(args.first) : true
|
180
|
+
comparison = result.is_a?(Regexp) ? '=~' : '=='
|
181
|
+
result = result.inspect
|
182
|
+
expression = "selenium.#{ruby_command}(#{ruby_args}).#{expectation} #{comparison} #{result}"
|
183
|
+
|
184
|
+
case verb
|
185
|
+
when 'assert'
|
186
|
+
expression
|
187
|
+
when 'verify'
|
188
|
+
"begin\n " +
|
189
|
+
"#{expression}\n " +
|
190
|
+
"rescue ::Test::Unit::AssertionFailedError, ::Spec::Expectations::ExpectationNotMetError => e\n " +
|
191
|
+
"@verification_errors << e\n " +
|
192
|
+
"end\n"
|
193
|
+
when 'waitFor'
|
194
|
+
"wait_for do\n #{expression}\n end\n"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.translate_command(command, target=nil, value=nil)
|
199
|
+
# p [:translate, command, target, value]
|
200
|
+
|
201
|
+
# TODO - custom treatment of patterns
|
202
|
+
# HACK / FIXME in the meantime
|
203
|
+
[target, value].compact.map(&:to_s).each { |s| s.gsub!(/^exact:/, '') }
|
204
|
+
|
205
|
+
if command.gsub!(/AndWait$/, '')
|
206
|
+
[translate_command(command, target, value), translate_command('waitForPageToLoad', default_timeout)].join("\n ")
|
207
|
+
elsif command =~ COMPOSITE && VARIANTS.has_key?($2)
|
208
|
+
build_composite_command(command, target, value)
|
209
|
+
else
|
210
|
+
case command
|
211
|
+
when 'pause'
|
212
|
+
"sleep #{target.to_i / 1000}"
|
213
|
+
when 'waitForPageToLoad'
|
214
|
+
"selenium.wait_for_page_to_load(\"#{default_timeout}\")"
|
215
|
+
else
|
216
|
+
ruby_command = underscore(command)
|
217
|
+
if client.respond_to?(ruby_command)
|
218
|
+
args = [target, value].compact
|
219
|
+
while args.length < client.method(ruby_command).arity
|
220
|
+
args << ""
|
221
|
+
end
|
222
|
+
"selenium.#{ruby_command} #{args.map(&:inspect).join(", ")}"
|
223
|
+
else
|
224
|
+
raise "unkown command error: #{command}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.underscore(str)
|
231
|
+
str.split(/([A-Z])/).inject("") { |s, ch| s << (ch =~ /[A-Z]/ ? "_#{ch.downcase}" : ch) }.gsub(/^_/,'')
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.client
|
235
|
+
@test_client ||= Selenium::Client::Driver.new(nil, nil, nil, nil)
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
|
data/rakefile.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# require 'vendor/gems/environment'
|
4
|
+
require File.join(File.dirname(__FILE__),"init")
|
5
|
+
Bundler.require_env :runner rescue nil
|
6
|
+
|
7
|
+
# load rake tasks
|
8
|
+
require 'rake'
|
9
|
+
require "spec/rake/spectask"
|
10
|
+
require "selenium/rake/tasks"
|
11
|
+
require "deep_test/rake_tasks"
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
gem.name = "rubidium"
|
17
|
+
gem.summary = %Q{convert Selenium tests to ruby/rspec for running against a Grid }
|
18
|
+
gem.description = %Q{convert Selenium tests to ruby/rspec for running against a Grid. Performs much better translation than the Selenium IDE, and a harness for running the resulting specs.}
|
19
|
+
gem.email = "david@davelee.com.au"
|
20
|
+
gem.homepage = "http://github.com/incite/rubidium"
|
21
|
+
gem.authors = ["davidlee"]
|
22
|
+
gem.add_development_dependency "jeweler", ">= 0"
|
23
|
+
gem.add_dependency "rake", ">= 0.8.7"
|
24
|
+
gem.add_dependency "selenium-client", "= 1.2.7"
|
25
|
+
gem.add_dependency "nokogiri", ">= 1.4.0"
|
26
|
+
gem.add_dependency "rspec", "= 1.1.8"
|
27
|
+
gem.add_dependency "deep_test", "= 1.2.2"
|
28
|
+
gem.add_dependency "ruby-debug", "> 0"
|
29
|
+
# gem.add_dependency "syntax"
|
30
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
31
|
+
end
|
32
|
+
Jeweler::GemcutterTasks.new
|
33
|
+
rescue LoadError
|
34
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Make sure we pick up the reporter from the appropriate selenium-client
|
39
|
+
# install as RSpec runner --require does not discriminate between multiple
|
40
|
+
# selenium-client gems.
|
41
|
+
gem_executable = Config::CONFIG["host_os"] =~ /mswin/ ? "gem.bat" : "gem"
|
42
|
+
report_formatter_path = `#{gem_executable} which -q "selenium/rspec/reporting/selenium_test_report_formatter"`.chomp
|
43
|
+
report_formatter_path.gsub!(/selenium-client-\d+\.\d+.\d+/, "selenium-client-1.2.7")
|
44
|
+
|
45
|
+
desc "Check whether you installed all dependencies and you environmnet is OK."
|
46
|
+
task :sanity_check do
|
47
|
+
require report_formatter_path
|
48
|
+
STDOUT.puts "yeah looks ok"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
52
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
53
|
+
t.spec_files = FileList['spec/**/*/*_spec.rb']
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'generate test suites'
|
57
|
+
task :generate do
|
58
|
+
root = File.dirname(__FILE__)
|
59
|
+
Rubidium::Converter.new(File.join(root,'examples/')).write!(File.join(root,'tmp/tests'))
|
60
|
+
end
|
61
|
+
|
62
|
+
task :convert do
|
63
|
+
root = File.dirname(__FILE__)
|
64
|
+
src_dir = 1
|
65
|
+
Rubidium::Converter.new(File.join(root,'examples/')).write!(File.join(root,'tmp/tests'))
|
66
|
+
end
|
67
|
+
|
68
|
+
task :default => :spec
|
data/rubidium.gemspec
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile.rb, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rubidium}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["davidlee"]
|
12
|
+
s.date = %q{2009-11-11}
|
13
|
+
s.description = %q{convert Selenium tests to ruby/rspec for running against a Grid. Performs much better translation than the Selenium IDE, and a harness for running the resulting specs.}
|
14
|
+
s.email = %q{david@davelee.com.au}
|
15
|
+
s.executables = ["bin/rubidium"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE",
|
18
|
+
"README",
|
19
|
+
"README.rdoc"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".gitignore",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE",
|
25
|
+
"README",
|
26
|
+
"README.rdoc",
|
27
|
+
"VERSION",
|
28
|
+
"examples/google.com/googleSuite.html",
|
29
|
+
"examples/google.com/sanityTest.html",
|
30
|
+
"init.rb",
|
31
|
+
"lib/rubidium.rb",
|
32
|
+
"lib/rubidium/converter.rb",
|
33
|
+
"lib/rubidium/spec_writer.rb",
|
34
|
+
"lib/rubidium/test_case.rb",
|
35
|
+
"lib/rubidium/test_suite.rb",
|
36
|
+
"lib/rubidium/translator.rb",
|
37
|
+
"rakefile.rb",
|
38
|
+
"rubidium.gemspec",
|
39
|
+
"script/rubidium",
|
40
|
+
"spec/rubidium/google.com/sanity_test_spec.rb",
|
41
|
+
"spec/rubidium_spec.rb",
|
42
|
+
"spec/spec_helper.rb",
|
43
|
+
"templates/rakefile.rb.erb",
|
44
|
+
"templates/spec.rb.erb",
|
45
|
+
"templates/spec_helper.rb.erb",
|
46
|
+
"todo.org"
|
47
|
+
]
|
48
|
+
s.homepage = %q{http://github.com/incite/rubidium}
|
49
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
50
|
+
s.require_paths = ["lib"]
|
51
|
+
s.rubygems_version = %q{1.3.5}
|
52
|
+
s.summary = %q{convert Selenium tests to ruby/rspec for running against a Grid}
|
53
|
+
s.test_files = [
|
54
|
+
"spec/rubidium/google.com/sanity_test_spec.rb",
|
55
|
+
"spec/rubidium_spec.rb",
|
56
|
+
"spec/spec_helper.rb"
|
57
|
+
]
|
58
|
+
|
59
|
+
if s.respond_to? :specification_version then
|
60
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
61
|
+
s.specification_version = 3
|
62
|
+
|
63
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
64
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
65
|
+
s.add_runtime_dependency(%q<rake>, [">= 0.8.7"])
|
66
|
+
s.add_runtime_dependency(%q<selenium-client>, ["= 1.2.7"])
|
67
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 1.4.0"])
|
68
|
+
s.add_runtime_dependency(%q<rspec>, ["= 1.1.8"])
|
69
|
+
s.add_runtime_dependency(%q<deep_test>, ["= 1.2.2"])
|
70
|
+
s.add_runtime_dependency(%q<ruby-debug>, ["> 0"])
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
73
|
+
s.add_dependency(%q<rake>, [">= 0.8.7"])
|
74
|
+
s.add_dependency(%q<selenium-client>, ["= 1.2.7"])
|
75
|
+
s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
|
76
|
+
s.add_dependency(%q<rspec>, ["= 1.1.8"])
|
77
|
+
s.add_dependency(%q<deep_test>, ["= 1.2.2"])
|
78
|
+
s.add_dependency(%q<ruby-debug>, ["> 0"])
|
79
|
+
end
|
80
|
+
else
|
81
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rake>, [">= 0.8.7"])
|
83
|
+
s.add_dependency(%q<selenium-client>, ["= 1.2.7"])
|
84
|
+
s.add_dependency(%q<nokogiri>, [">= 1.4.0"])
|
85
|
+
s.add_dependency(%q<rspec>, ["= 1.1.8"])
|
86
|
+
s.add_dependency(%q<deep_test>, ["= 1.2.2"])
|
87
|
+
s.add_dependency(%q<ruby-debug>, ["> 0"])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../../spec_helper.rb')
|
2
|
+
|
3
|
+
describe "sanity check w/ google" do
|
4
|
+
before do
|
5
|
+
@test = Rubidium::TestCase.new f 'examples/google.com/sanityTest.html'
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is called sanityTest" do
|
9
|
+
@test.name.should == 'sanityTest'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "operates on google.com.au" do
|
13
|
+
@test.base_url.should == "http://www.google.com.au/"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has a table of selenese commands" do
|
17
|
+
@test.table.should == [
|
18
|
+
["open", "/"],
|
19
|
+
["assertTextPresent", "Google"],
|
20
|
+
["assertTextNotPresent", "Bing"],
|
21
|
+
["type", "q", "wikipedia"],
|
22
|
+
["keyPress", "q", "\\13"],
|
23
|
+
["waitForElementPresent", "css=a.l"],
|
24
|
+
["verifyTextPresent", "Wikipedia, the free encyclopedia"],
|
25
|
+
["assertElementPresent", "link=Wikipedia, the free encyclopedia"]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe "spec writer" do
|
4
|
+
describe "convert a test case" do
|
5
|
+
before do
|
6
|
+
@test_case = Rubidium::TestCase.new(f('examples/google.com/sanityTest.html'))
|
7
|
+
@writer = Rubidium::SpecWriter.new(f('tmp/tests'))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "generate a spec file" do
|
11
|
+
@test_case.should be_kind_of Rubidium::TestCase
|
12
|
+
@writer.write!(@test_case)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "convert a directory" do
|
17
|
+
it "convert test suites" do
|
18
|
+
converter = Rubidium::Converter.new f('examples/')
|
19
|
+
converter.write! f('tmp/suites')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
require <%= File.expand_path(f 'init').inspect %>
|
3
|
+
|
4
|
+
require "rake"
|
5
|
+
require "spec/rake/spectask"
|
6
|
+
require "selenium/rake/tasks"
|
7
|
+
require "deep_test/rake_tasks"
|
8
|
+
|
9
|
+
# Make sure we pick up the reporter from the appropriate selenium-client
|
10
|
+
# install as RSpec runner --require does not discriminate between multiple
|
11
|
+
# selenium-client gems.
|
12
|
+
gem_executable = Config::CONFIG["host_os"] =~ /mswin/ ? "gem.bat" : "gem"
|
13
|
+
report_formatter_path = `#{gem_executable} which -q "selenium/rspec/reporting/selenium_test_report_formatter"`.chomp
|
14
|
+
report_formatter_path.gsub! /selenium-client-\d+\.\d+.\d+/, "selenium-client-1.2.7"
|
15
|
+
|
16
|
+
|
17
|
+
#
|
18
|
+
# Recommended way to run tests in parallel and leverage Selenium Grid.
|
19
|
+
#
|
20
|
+
|
21
|
+
desc("Run all tests in parallel using DeepTest.")
|
22
|
+
Spec::Rake::SpecTask.new("tests:run_in_parallel") do |t|
|
23
|
+
t.spec_files = FileList['./**/*_spec.rb']
|
24
|
+
t.deep_test :number_of_workers => 6,
|
25
|
+
:timeout_in_seconds => 300
|
26
|
+
t.spec_opts << '--color'
|
27
|
+
t.spec_opts << "--require 'rubygems,#{report_formatter_path}'"
|
28
|
+
t.spec_opts << "--format=Selenium::RSpec::SeleniumTestReportFormatter:./tmp/test_report.html"
|
29
|
+
t.spec_opts << "--format=progress"
|
30
|
+
end
|
31
|
+
task :'tests:run_in_parallel' => :create_report_dir
|
32
|
+
#
|
33
|
+
# Running tests in sequence (without taking advantage of Selenium Grid),
|
34
|
+
# useful to troubleshoot problems with the parallel run.
|
35
|
+
#
|
36
|
+
|
37
|
+
desc "Run all behaviors in sequence"
|
38
|
+
Spec::Rake::SpecTask.new('tests:run_in_sequence') do |t|
|
39
|
+
t.pattern = "./**/*_spec.rb"
|
40
|
+
t.spec_opts << '--color'
|
41
|
+
t.spec_opts << "--require 'rubygems,#{report_formatter_path}'"
|
42
|
+
t.spec_opts << "--format=Selenium::RSpec::SeleniumTestReportFormatter:./tmp/test_report.html"
|
43
|
+
t.spec_opts << "--format=progress"
|
44
|
+
t.fail_on_error = true
|
45
|
+
end
|
46
|
+
task :'tests:run_in_sequence' => :create_report_dir
|
47
|
+
|
48
|
+
task :create_report_dir do
|
49
|
+
rm_f File.expand_path(File.dirname(__FILE__) + "/tmp/rspec_report")
|
50
|
+
mkdir_p File.expand_path(File.dirname(__FILE__) + "/tmp/rspec_report")
|
51
|
+
ENV['SELENIUM_TEST_REPORT_FILE'] = "./tmp/test_report.html" # Workaround for DeepTest reports
|
52
|
+
end
|
53
|
+
|
54
|
+
task :p => :'tests:run_in_parallel'
|
55
|
+
task :s => :'tests:run_in_sequence'
|
56
|
+
task :default => :s
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# this is a selenium test case generated by Rubidium.
|
2
|
+
# do not edit this file directly.
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), '../spec_helper')
|
5
|
+
|
6
|
+
describe "<%= @test_case && @test_suite.name || @test_case.name %>" do
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
create_selenium_driver({ :application_url => <%= @application_url.inspect %> })
|
10
|
+
start_new_browser_session
|
11
|
+
@verification_errors = []
|
12
|
+
end
|
13
|
+
|
14
|
+
it "<%= @test_case.name %>" do
|
15
|
+
<%= @test_case.commands.join("\n ") %>
|
16
|
+
end
|
17
|
+
|
18
|
+
after :each do
|
19
|
+
@selenium_driver.stop
|
20
|
+
@verification_errors.should == []
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# this is the helper
|
2
|
+
|
3
|
+
require <%= File.expand_path(f 'init').inspect %>
|
4
|
+
|
5
|
+
require "rake"
|
6
|
+
require 'spec/rake/spectask'
|
7
|
+
require "selenium/rake/tasks"
|
8
|
+
require "selenium/client"
|
9
|
+
require "selenium/rspec/spec_helper"
|
10
|
+
require "deep_test/rake_tasks"
|
11
|
+
|
12
|
+
module SeleniumTestHelper
|
13
|
+
|
14
|
+
def wait_for(params={})
|
15
|
+
timeout = params[:timeout] || 5
|
16
|
+
message = params[:message] || "Timeout exceeded"
|
17
|
+
|
18
|
+
begin_time = Time.now
|
19
|
+
|
20
|
+
while (Time.now - begin_time) < timeout
|
21
|
+
value = nil
|
22
|
+
|
23
|
+
begin
|
24
|
+
value = yield
|
25
|
+
rescue Exception => e
|
26
|
+
unless is_ignorable_wait_for_exception?(e)
|
27
|
+
raise e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
return value if value
|
32
|
+
|
33
|
+
sleep 0.25
|
34
|
+
end
|
35
|
+
|
36
|
+
raise Webrat::TimeoutError.new(message + " (after #{timeout} sec)")
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def is_ignorable_wait_for_exception?(exception) #:nodoc:
|
43
|
+
if defined?(::Spec::Expectations::ExpectationNotMetError)
|
44
|
+
return true if exception.class == ::Spec::Expectations::ExpectationNotMetError
|
45
|
+
end
|
46
|
+
return [::Selenium::CommandError].include?(exception.class)
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_new_browser_session
|
50
|
+
@selenium_driver.start_new_browser_session
|
51
|
+
@selenium_driver.set_context "Starting example '#{self.description}'"
|
52
|
+
end
|
53
|
+
|
54
|
+
def selenium_driver
|
55
|
+
@selenium_driver
|
56
|
+
end
|
57
|
+
|
58
|
+
def selenium
|
59
|
+
@selenium_driver
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_selenium_driver(options={})
|
63
|
+
options = {
|
64
|
+
"grid_host" => ( ENV['SELENIUM_RC_HOST'] || 'localhost'),
|
65
|
+
"grid_port" => ( ENV['SELENIUM_RC_PORT'] || '4444'),
|
66
|
+
"browser" => ( ENV['SELENIUM_RC_BROWSER'] || '*firefox'),
|
67
|
+
"timeout" => ( ENV['SELENIUM_RC_TIMEOUT'] || '10000'),
|
68
|
+
"app_host" => ( ENV['SELENIUM_APPLICATION_HOST'] || 'localhost'),
|
69
|
+
"app_port" => ( ENV['SELENIUM_APPLICATION_PORT'] || '4000'),
|
70
|
+
}.merge(options)
|
71
|
+
|
72
|
+
options['application_url'] ||= "http://#{options['app_host']}:#{options['app_port']}"
|
73
|
+
|
74
|
+
@selenium_driver = Selenium::Client::Driver.new(
|
75
|
+
options['grid_host'],
|
76
|
+
options['grid_port'],
|
77
|
+
options['browser'],
|
78
|
+
options['application_url'],
|
79
|
+
options['timeout'].to_i
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
Spec::Runner.configure do |config|
|
86
|
+
config.include SeleniumTestHelper
|
87
|
+
|
88
|
+
config.before(:each) do
|
89
|
+
create_selenium_driver
|
90
|
+
start_new_browser_session
|
91
|
+
@verification_errors = []
|
92
|
+
end
|
93
|
+
|
94
|
+
# The system capture need to happen BEFORE the closing the Selenium session
|
95
|
+
config.append_after(:each) do
|
96
|
+
@selenium_driver.close_current_browser_session
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
end
|
data/todo.org
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubidium
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- davidlee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-11 00:00:00 +11:00
|
13
|
+
default_executable: rubidium
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: jeweler
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.7
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: selenium-client
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.2.7
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: nokogiri
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.4.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.1.8
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: deep_test
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.2.2
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: ruby-debug
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
description: convert Selenium tests to ruby/rspec for running against a Grid. Performs much better translation than the Selenium IDE, and a harness for running the resulting specs.
|
86
|
+
email: david@davelee.com.au
|
87
|
+
executables:
|
88
|
+
- rubidium
|
89
|
+
extensions: []
|
90
|
+
|
91
|
+
extra_rdoc_files:
|
92
|
+
- LICENSE
|
93
|
+
- README
|
94
|
+
- README.rdoc
|
95
|
+
files:
|
96
|
+
- .gitignore
|
97
|
+
- Gemfile
|
98
|
+
- LICENSE
|
99
|
+
- README
|
100
|
+
- README.rdoc
|
101
|
+
- VERSION
|
102
|
+
- bin/rubidium
|
103
|
+
- examples/google.com/googleSuite.html
|
104
|
+
- examples/google.com/sanityTest.html
|
105
|
+
- init.rb
|
106
|
+
- lib/rubidium.rb
|
107
|
+
- lib/rubidium/converter.rb
|
108
|
+
- lib/rubidium/spec_writer.rb
|
109
|
+
- lib/rubidium/test_case.rb
|
110
|
+
- lib/rubidium/test_suite.rb
|
111
|
+
- lib/rubidium/translator.rb
|
112
|
+
- rakefile.rb
|
113
|
+
- rubidium.gemspec
|
114
|
+
- spec/rubidium/google.com/sanity_test_spec.rb
|
115
|
+
- spec/rubidium_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- templates/rakefile.rb.erb
|
118
|
+
- templates/spec.rb.erb
|
119
|
+
- templates/spec_helper.rb.erb
|
120
|
+
- todo.org
|
121
|
+
has_rdoc: true
|
122
|
+
homepage: http://github.com/incite/rubidium
|
123
|
+
licenses: []
|
124
|
+
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options:
|
127
|
+
- --charset=UTF-8
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: "0"
|
135
|
+
version:
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: "0"
|
141
|
+
version:
|
142
|
+
requirements: []
|
143
|
+
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 1.3.5
|
146
|
+
signing_key:
|
147
|
+
specification_version: 3
|
148
|
+
summary: convert Selenium tests to ruby/rspec for running against a Grid
|
149
|
+
test_files:
|
150
|
+
- spec/rubidium/google.com/sanity_test_spec.rb
|
151
|
+
- spec/rubidium_spec.rb
|
152
|
+
- spec/spec_helper.rb
|