rubidium 0.0.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.
- 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
|