selenium-selenese 1.1.3

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 (31) hide show
  1. data/README.markdown +308 -0
  2. data/examples/script/google.rb +15 -0
  3. data/lib/nautilus/shell.rb +32 -0
  4. data/lib/selenium.rb +14 -0
  5. data/lib/selenium/client/base.rb +140 -0
  6. data/lib/selenium/client/driver.rb +11 -0
  7. data/lib/selenium/client/extensions.rb +118 -0
  8. data/lib/selenium/client/idiomatic.rb +488 -0
  9. data/lib/selenium/client/javascript_expression_builder.rb +116 -0
  10. data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
  11. data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
  12. data/lib/selenium/client/legacy_driver.rb +1711 -0
  13. data/lib/selenium/client/protocol.rb +131 -0
  14. data/lib/selenium/client/selenium_helper.rb +36 -0
  15. data/lib/selenium/command_error.rb +4 -0
  16. data/lib/selenium/protocol_error.rb +4 -0
  17. data/lib/selenium/rake/default_tasks.rb +16 -0
  18. data/lib/selenium/rake/remote_control_start_task.rb +71 -0
  19. data/lib/selenium/rake/remote_control_stop_task.rb +44 -0
  20. data/lib/selenium/rake/tasks.rb +6 -0
  21. data/lib/selenium/remote_control/remote_control.rb +35 -0
  22. data/lib/selenium/rspec/reporting/file_path_strategy.rb +78 -0
  23. data/lib/selenium/rspec/reporting/html_report.rb +123 -0
  24. data/lib/selenium/rspec/reporting/selenium_test_report_formatter.rb +87 -0
  25. data/lib/selenium/rspec/reporting/system_capture.rb +72 -0
  26. data/lib/selenium/rspec/rspec_extensions.rb +96 -0
  27. data/lib/selenium/rspec/spec_helper.rb +34 -0
  28. data/lib/selenium/selenese.rb +24 -0
  29. data/lib/tcp_socket_extension.rb +32 -0
  30. data/vendor/selenium-server.jar +0 -0
  31. metadata +101 -0
@@ -0,0 +1,131 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ HTTP_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8' }
5
+
6
+ # Module in charge of handling Selenium over-the-wire HTTP protocol
7
+ module Protocol
8
+
9
+ $commands = []
10
+
11
+ attr_reader :session_id
12
+
13
+ def remote_control_command(verb, args=[])
14
+ timeout(@default_timeout_in_seconds) do
15
+ status, response = http_post(http_request_for(verb, args))
16
+ raise Selenium::CommandError, response unless status == "OK"
17
+ response[3..-1] # strip "OK," from response
18
+ end
19
+ end
20
+
21
+ def string_command(verb, args=[])
22
+ remote_control_command(verb, args)
23
+ end
24
+
25
+ def string_array_command(verb, args=[])
26
+ csv = string_command(verb, args)
27
+ token = ""
28
+ tokens = []
29
+ escape = false
30
+ csv.split(//).each do |letter|
31
+ if escape
32
+ token += letter
33
+ escape = false
34
+ next
35
+ end
36
+ case letter
37
+ when '\\'
38
+ escape = true
39
+ when ','
40
+ tokens << token
41
+ token = ""
42
+ else
43
+ token += letter
44
+ end
45
+ end
46
+ tokens << token
47
+ return tokens
48
+ end
49
+
50
+ def number_command(verb, args)
51
+ string_command verb, args
52
+ end
53
+
54
+ def number_array_command(verb, args)
55
+ string_array_command verb, args
56
+ end
57
+
58
+ def boolean_command(verb, args=[])
59
+ parse_boolean_value string_command(verb, args)
60
+ end
61
+
62
+ def boolean_array_command(verb, args)
63
+ string_array_command(verb, args).collect {|value| parse_boolean_value(value)}
64
+ end
65
+
66
+ protected
67
+
68
+ def parse_boolean_value(value)
69
+ if ("true" == value)
70
+ return true
71
+ elsif ("false" == value)
72
+ return false
73
+ end
74
+ raise ProtocolError, "Invalid Selenese boolean value that is neither 'true' nor 'false': got '#{value}'"
75
+ end
76
+
77
+ def http_request_for(verb, args)
78
+ data = "cmd=#{CGI::escape(verb)}"
79
+ args.each_with_index do |arg, index|
80
+ data << "&#{index.succ}=#{CGI::escape(arg.to_s)}"
81
+ end
82
+ data << "&sessionId=#{session_id}" unless session_id.nil?
83
+ data
84
+ end
85
+
86
+ def http_post(data)
87
+ dummy_data = data
88
+ start = Time.now
89
+ called_from = caller.detect{|line| line !~ /(selenium-client|vendor|usr\/lib\/ruby|\(eval\))/i}
90
+ http = Net::HTTP.new(@host, @port)
91
+ http.open_timeout = default_timeout_in_seconds
92
+ http.read_timeout = default_timeout_in_seconds
93
+ response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
94
+ if response.body !~ /^OK/
95
+ puts "#{start} selenium-client received failure from selenium server:"
96
+ puts "requested:"
97
+ puts "\t" + CGI::unescape(data.split('&').join("\n\t"))
98
+ puts "received:"
99
+ puts "\t#{response.body.inspect}"
100
+ puts "\tcalled from #{called_from}"
101
+ end
102
+ cmd = []
103
+ dummy_data = "" if dummy_data.include?("getNewBrowserSession")
104
+ if dummy_data != ""
105
+ command = dummy_data.split('&')
106
+ command.delete_if{|str| str.include?("sessionId")}
107
+ command.collect{|str|
108
+ cmd << str.gsub!("cmd=","") if str.include?("cmd=")
109
+ cmd << CGI::unescape(str.gsub!("1=",""))if str.include?("1=")
110
+ cmd << CGI::unescape(str.gsub!("2=","")) if str.include?("2=")
111
+ }
112
+ $commands << cmd
113
+ end
114
+ [ response.body[0..1], response.body ]
115
+ end
116
+
117
+ def selenese_script
118
+
119
+ selenese_commands = ""
120
+ $commands.collect do |command|
121
+ selenese_commands << "<tr><td>#{command[0]}</td><td>#{command[1]}</td><td>#{command[2]}</td></tr>"
122
+ end
123
+
124
+ script = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head profile="http://selenium-ide.openqa.org/profiles/test-case"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><link rel="selenium.base" href="http://www.google.co.in/" /><title>myscript<title></head><body><table cellpadding="1" cellspacing="1" border="1"><thead><tr><td rowspan="1" colspan="3">myscript</td></tr></thead><tbody>'+selenese_commands+'</tbody></table></body></html>'
125
+ return script
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,36 @@
1
+ # Defines a mixin module that you can use to write Selenium tests
2
+ # without typing "@selenium." in front of every command. Every
3
+ # call to a missing method will be automatically sent to the @selenium
4
+ # object.
5
+ module Selenium
6
+ module Client
7
+
8
+ module SeleniumHelper
9
+
10
+ # Overrides default open method to actually delegates to @selenium
11
+ def open(url)
12
+ puts "Inside Help Open"
13
+ @selenium.open url
14
+ end
15
+
16
+ # Overrides default type method to actually delegates to @selenium
17
+ def type(locator, value)
18
+ puts "Inside Help type"
19
+ @selenium.type locator, value
20
+ end
21
+
22
+ # Overrides default select method to actually delegates to @selenium
23
+ def select(input_locator, option_locator)
24
+ @selenium.select input_locator, option_locator
25
+ end
26
+
27
+ # Delegates to @selenium on method missing
28
+ def method_missing(method_name, *args)
29
+ return super unless @selenium.respond_to?(method_name)
30
+
31
+ @selenium.send(method_name, *args)
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,4 @@
1
+ module Selenium
2
+ class CommandError < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Selenium
2
+ class ProtocolError < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,16 @@
1
+ require 'selenium/rake/tasks'
2
+
3
+ Selenium::Rake::RemoteControlStartTask.new do |rc|
4
+ rc.timeout_in_seconds = 3 * 60
5
+ rc.background = true
6
+ rc.wait_until_up_and_running = true
7
+ rc.additional_args << "-singleWindow"
8
+ end
9
+
10
+ Selenium::Rake::RemoteControlStopTask.new
11
+
12
+ desc "Restart Selenium Remote Control"
13
+ task :'selenium:rc:restart' do
14
+ Rake::Task[:'selenium:rc:stop'].execute [] rescue nil
15
+ Rake::Task[:'selenium:rc:start'].execute []
16
+ end
@@ -0,0 +1,71 @@
1
+ module Selenium
2
+ module Rake
3
+
4
+ # Rake tasks to start a Remote Control server.
5
+ #
6
+ # require 'selenium/rake/tasks'
7
+ #
8
+ # Selenium::Rake::RemoteControlStartTask.new do |rc|
9
+ # rc.port = 4444
10
+ # rc.timeout_in_seconds = 3 * 60
11
+ # rc.background = true
12
+ # rc.wait_until_up_and_running = true
13
+ # rc.jar_file = "/path/to/where/selenium-rc-standalone-jar-is-installed"
14
+ # rc.additional_args << "-singleWindow"
15
+ # end
16
+ #
17
+ # If you do not explicitly specify the path to selenium remote control jar
18
+ # it will be "auto-discovered" in `vendor` directory using the following
19
+ # path : `vendor/selenium-remote-control/selenium-server*-standalone.jar`
20
+ #
21
+ # To leverage the latest selenium-client capabilities, you may need to download
22
+ # a recent nightly build of a standalone packaging of Selenium Remote
23
+ # Control. You will find the nightly build at
24
+ # http://nexus.openqa.org/content/repositories/snapshots/org/seleniumhq/selenium/server/selenium-server/
25
+ class RemoteControlStartTask
26
+ attr_accessor :host, :port, :timeout_in_seconds, :background,
27
+ :wait_until_up_and_running, :additional_args,
28
+ :log_to
29
+ attr_reader :jar_file
30
+
31
+ JAR_FILE_PATTERN = "vendor/selenium-remote-control/selenium-server-*.jar"
32
+
33
+ def initialize(name = :'selenium:rc:start')
34
+ @name = name
35
+ @host = "localhost"
36
+ @port = 4444
37
+ @timeout_in_seconds = 5
38
+ project_specific_jar = Dir[JAR_FILE_PATTERN].first
39
+ @jar_file = project_specific_jar
40
+ @additional_args = []
41
+ @background = false
42
+ @wait_until_up_and_running = false
43
+ yield self if block_given?
44
+ define
45
+ end
46
+
47
+ def jar_file=(new_jar_file)
48
+ @jar_file = File.expand_path(new_jar_file)
49
+ end
50
+
51
+ def define
52
+ desc "Launch Selenium Remote Control"
53
+ task @name do
54
+ puts "Starting Selenium Remote Control at 0.0.0.0:#{@port}..."
55
+ raise "Could not find jar file '#{@jar_file}'. Expected it under #{JAR_FILE_PATTERN}" unless @jar_file && File.exists?(@jar_file)
56
+ remote_control = Selenium::RemoteControl::RemoteControl.new("0.0.0.0", @port, :timeout => @timeout_in_seconds)
57
+ remote_control.jar_file = @jar_file
58
+ remote_control.additional_args = @additional_args
59
+ remote_control.log_to = @log_to
60
+ remote_control.start :background => @background
61
+ if @background && @wait_until_up_and_running
62
+ puts "Waiting for Remote Control to be up and running..."
63
+ TCPSocket.wait_for_service :host => @host, :port => @port
64
+ end
65
+ puts "Selenium Remote Control at 0.0.0.0:#{@port} ready"
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,44 @@
1
+ module Selenium
2
+ module Rake
3
+
4
+ # Rake task to stop a Selenium Remote Control Server
5
+ #
6
+ # Selenium::Rake::RemoteControlStopTask.new do |rc|
7
+ # rc.host = "localhost"
8
+ # rc.port = 4444
9
+ # rc.timeout_in_seconds = 3 * 60
10
+ # end
11
+ #
12
+ class RemoteControlStopTask
13
+ attr_accessor :host, :port, :timeout_in_seconds, :wait_until_stopped,
14
+ :shutdown_command
15
+
16
+ def initialize(name = :'selenium:rc:stop')
17
+ @host = "localhost"
18
+ @name = name
19
+ @port = 4444
20
+ @timeout_in_seconds = nil
21
+ @shutdown_command = nil
22
+ @wait_until_stopped = true
23
+ yield self if block_given?
24
+ define
25
+ end
26
+
27
+ def define
28
+ desc "Stop Selenium Remote Control running"
29
+ task @name do
30
+ puts "Stopping Selenium Remote Control running at #{host}:#{port}..."
31
+ remote_control = Selenium::RemoteControl::RemoteControl.new(
32
+ host, port, :timeout => timeout_in_seconds,
33
+ :shutdown_command => shutdown_command)
34
+ remote_control.stop
35
+ if @wait_until_stopped
36
+ TCPSocket.wait_for_service_termination :host => host, :port => port
37
+ end
38
+ puts "Stopped Selenium Remote Control running at #{host}:#{port}"
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ require "net/http"
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../nautilus/shell')
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../tcp_socket_extension')
4
+ require File.expand_path(File.dirname(__FILE__) + '/../remote_control/remote_control')
5
+ require File.expand_path(File.dirname(__FILE__) + '/remote_control_start_task')
6
+ require File.expand_path(File.dirname(__FILE__) + '/remote_control_stop_task')
@@ -0,0 +1,35 @@
1
+ module Selenium
2
+ module RemoteControl
3
+
4
+ class RemoteControl
5
+ attr_reader :host, :port, :timeout_in_seconds, :firefox_profile, :shutdown_command
6
+ attr_accessor :additional_args, :jar_file, :log_to
7
+
8
+ def initialize(host, port, options={})
9
+ @host, @port = host, port
10
+ @timeout_in_seconds = options[:timeout] || (2 * 60)
11
+ @shutdown_command = options[:shutdown_command] || "shutDownSeleniumServer"
12
+ @firefox_profile = options[:firefox_profile]
13
+ @additional_args = options[:additional_args] || []
14
+ @shell = Nautilus::Shell.new
15
+ end
16
+
17
+ def start(options = {})
18
+ command = "java -jar \"#{jar_file}\""
19
+ command << " -port #{@port}"
20
+ command << " -timeout #{@timeout_in_seconds}"
21
+ command << " -firefoxProfileTemplate '#{@firefox_profile}'" if @firefox_profile
22
+ command << " #{additional_args.join(' ')}" unless additional_args.empty?
23
+ command << " > #{log_to}" if log_to
24
+
25
+ @shell.run command, {:background => options[:background]}
26
+ end
27
+
28
+ def stop
29
+ Net::HTTP.get(@host, "/selenium-server/driver/?cmd=#{shutdown_command}", @port)
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ module Selenium
2
+ module RSpec
3
+ module Reporting
4
+
5
+ class FilePathStrategy
6
+ attr_reader :final_report_file_path
7
+
8
+ REPORT_DEFAULT_FILE_PATH = File.join(Dir::tmpdir, "selenium_test_report", "index.html")
9
+
10
+ def initialize(final_report_file_path)
11
+ @final_report_file_path = final_report_file_path || REPORT_DEFAULT_FILE_PATH
12
+ @relative_dir = nil
13
+ end
14
+
15
+ def base_report_dir
16
+ @base_report_dir ||= File.dirname(File.expand_path(@final_report_file_path))
17
+ end
18
+
19
+ def relative_dir
20
+ return @relative_dir if @relative_dir
21
+
22
+ file_name_without_extension = File.basename(@final_report_file_path).sub(/\.[^\.]*$/, "")
23
+ @relative_dir ||= "resources/" + file_name_without_extension
24
+ end
25
+
26
+ def relative_file_path_for_html_capture(example)
27
+ "#{relative_dir}/example_#{example.reporting_uid}.html"
28
+ end
29
+
30
+ def relative_file_path_for_system_screenshot(example)
31
+ "#{relative_dir}/example_#{example.reporting_uid}_system_screenshot.png"
32
+ end
33
+
34
+ def relative_file_path_for_page_screenshot(example)
35
+ "#{relative_dir}/example_#{example.reporting_uid}_page_screenshot.png"
36
+ end
37
+
38
+ def relative_file_path_for_remote_control_logs(example)
39
+ "#{relative_dir}/example_#{example.reporting_uid}_remote_control.log"
40
+ end
41
+
42
+ def relative_file_path_for_browser_network_traffic(example)
43
+ "#{relative_dir}/example_#{example.reporting_uid}_browser_network_traffic.log"
44
+ end
45
+
46
+ def file_path_for_html_capture(example)
47
+ file_path relative_file_path_for_html_capture(example)
48
+ end
49
+
50
+ def file_path_for_system_screenshot(example)
51
+ file_path relative_file_path_for_system_screenshot(example)
52
+ end
53
+
54
+ def file_path_for_page_screenshot(example)
55
+ file_path relative_file_path_for_page_screenshot(example)
56
+ end
57
+
58
+ def file_path_for_remote_control_logs(example)
59
+ file_path relative_file_path_for_remote_control_logs(example)
60
+ end
61
+
62
+ def file_path_for_browser_network_traffic(example)
63
+ file_path relative_file_path_for_browser_network_traffic(example)
64
+ end
65
+
66
+ def file_path(relative_file_path)
67
+ the_file_path = base_report_dir + "/" + relative_file_path
68
+ parent_dir = File.dirname(the_file_path)
69
+ FileUtils.mkdir_p(parent_dir) unless File.directory?(parent_dir)
70
+ the_file_path
71
+ end
72
+
73
+
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,123 @@
1
+ module Selenium
2
+ module RSpec
3
+ module Reporting
4
+
5
+ class HtmlReport
6
+
7
+ PLACEHOLDER = "<<placeholder>>"
8
+
9
+ def initialize(file_path_strategy)
10
+ @file_path_strategy = file_path_strategy
11
+ end
12
+
13
+ def self.inject_placeholder(content)
14
+ content + Selenium::RSpec::Reporting::HtmlReport::PLACEHOLDER
15
+ end
16
+
17
+ def replace_placeholder_with_system_state_content(result, example)
18
+ result.gsub! PLACEHOLDER, logs_and_screenshot_sections(example)
19
+ end
20
+
21
+ def logs_and_screenshot_sections(example)
22
+ dom_id = "example_" + example.reporting_uid
23
+ system_screenshot_url = @file_path_strategy.relative_file_path_for_system_screenshot(example)
24
+ page_screenshot_url = @file_path_strategy.relative_file_path_for_page_screenshot(example)
25
+ snapshot_url = @file_path_strategy.relative_file_path_for_html_capture(example)
26
+ remote_control_logs_url = @file_path_strategy.relative_file_path_for_remote_control_logs(example)
27
+
28
+ html = ""
29
+ if File.exists? @file_path_strategy.file_path_for_html_capture(example)
30
+ html << toggable_section(dom_id, :id => "snapshot", :url=> snapshot_url, :name => "Dynamic HTML Snapshot")
31
+ end
32
+ if File.exists? @file_path_strategy.file_path_for_remote_control_logs(example)
33
+ html << toggable_section(dom_id, :id => "rc_logs", :url=> remote_control_logs_url, :name => "Remote Control Logs")
34
+ end
35
+ if File.exists? @file_path_strategy.file_path_for_page_screenshot(example)
36
+ html << toggable_image_section(dom_id, :id => "page_screenshot", :name => "Page Screenshot", :url => page_screenshot_url)
37
+ end
38
+ if File.exists? @file_path_strategy.file_path_for_system_screenshot(example)
39
+ html << toggable_image_section(dom_id, :id => "system_screenshot", :name => "System Screenshot", :url => system_screenshot_url)
40
+ end
41
+
42
+ return html
43
+ end
44
+
45
+ def self.append_javascript(global_scripts)
46
+ global_scripts + <<-EOF
47
+ function toggleVisilibility(id, description) {
48
+ var section;
49
+ var link;
50
+
51
+ section = document.getElementById(id);
52
+ link = document.getElementById(id + "_link");
53
+
54
+ if (section.style.display == "block") {
55
+ section.style.display = "none"
56
+ link.innerHTML = "Show " + description
57
+ } else {
58
+ section.style.display = "block"
59
+ link.innerHTML = "Hide " + description
60
+ }
61
+ }
62
+ EOF
63
+ end
64
+
65
+ def self.append_css(global_styles)
66
+ global_styles + <<-EOF
67
+
68
+ div.rspec-report textarea {
69
+ width: 100%;
70
+ }
71
+
72
+ div.rspec-report .dyn-source {
73
+ background: #FFFFEE none repeat scroll 0%;
74
+ border:1px dotted black;
75
+ color: #000000;
76
+ display: none;
77
+ margin: 0.5em 2em;
78
+ padding: 0.5em;
79
+ }
80
+
81
+ EOF
82
+ end
83
+
84
+ def toggable_section(dom_id, options)
85
+ <<-EOS
86
+
87
+ <div>[
88
+ <a id="#{dom_id}_#{options[:id]}_link"
89
+ href=\"javascript:toggleVisilibility('#{dom_id}_#{options[:id]}', '#{options[:name]}')\">Show #{options[:name]}</a>
90
+ ]</div>
91
+ <br/><br/>
92
+ <div id="#{dom_id}_#{options[:id]}" class="dyn-source">
93
+ <a href="#{options[:url]}">Full screen</a><br/><br/>
94
+ <iframe src="#{options[:url]}" width="100%" height="600px" ></iframe>
95
+ </div>
96
+
97
+ EOS
98
+ end
99
+
100
+ def toggable_image_section(dom_id, options)
101
+ <<-EOS
102
+
103
+ <div>[<a id="#{dom_id}_#{options[:id]}_link" href="javascript:toggleVisilibility('#{dom_id}_#{options[:id]}', '#{options[:name]}');">Show #{options[:name]}</a>]</div>
104
+ <br/>
105
+ <div id="#{dom_id}_#{options[:id]}" style="display: none">
106
+ <a href="#{options[:url]}">
107
+ <img width="80%" src="#{options[:url]}" />
108
+ </a>
109
+ </div>
110
+ <br/>
111
+
112
+ EOS
113
+ end
114
+
115
+ def report_header
116
+ super + "\n<script type=\"text/javascript\">moveProgressBar('100.0');</script>"
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ end
123
+ end