# IDE Class to run an IDE based HTML suite after transforming it based on oats_data
module Oats
# Runs an IDE based HTML suite after transforming it based on current Oats data
class Ide
def initialize()
super
@suite_base_url_signin_type = nil;
@first_test_url = nil;
end
# Run input_suite_path while in a TestData.dir . Assumes Oats.data is initialized for TestData.dir
# input_suite_path:: path to the suite HTML
# hash:: list from => to values to use for regeneration of the included test cases.
def run (input_suite_path, hash = nil )
begin
run_ide(input_suite_path, hash)
ensure
TestData.current_test.collect_downloaded_output
end
end
private
def run_ide (input_suite_path, hash = nil )
suite_path = get_path(input_suite_path)
name = File.basename(suite_path)
doc = open(suite_path ) { |f| Hpricot(f) }
# FileUtils.rm Dir[File.join(TestData.current_test.dir,'*.gen.*')] # Clean previously generated files
FileUtils.rm Dir['*.gen.*'] # Clean previously generated files in pwd
if doc.search("head[@profile='http://selenium-ide.openqa.org/profiles/test-case']").empty?
regen_suite = nil
doc.search('a[@href]') do |a|
if Oats.data['execution']['run_in_dir_results']
generated_test = regenerate_html(a['href'], test.result, File.dirname(suite_path), hash)
else
generated_test = regenerate_html(a['href'], test.dir, File.dirname(suite_path), hash)
end
if generated_test
regen_suite = true
a.set_attribute(:href,generated_test)
end
end
html_suite_path = File.join(test.dir , File.basename(suite_path,'.*') + '.gen.html')
regen_suite = true if regen_suite or html_suite_path != suite_path
html_suite_path = File.join(test.result , File.basename(suite_path,'.*') + '.gen.html') if Oats.data['execution']['run_in_dir_results']
$log.info "Creating: #{html_suite_path}"
File.open( html_suite_path, 'w' ) { |out| out.print doc } if regen_suite
else # A single test HTML, not the suite
raise OatsTestError, "Input file is not an IDE suite: " + html_suite_path
end
# Execute html_suite_path
result_file = File.join(test.result, File.basename(name, '.*') + '_results.html')
if Oats.data['selenium']['ide']['generate']
$log.warn "Option execution:ide:generate is set. Test will not be executed."
$log.debug "Target result_file was: #{result_file}"
return
end
rc_jar_file = File.join(Oats.data['_']['vendor'],'selenium-server.jar')
browser = '*' + Oats.data['selenium']['browser_type'].sub(/ .*/,'')
url = nil
if @suite_base_url_signin_type
url = Oats.data[@suite_base_url_signin_type]["SignIn"]["url"]
else
if @first_test_url
url = @first_test_url
else
raise(OatsError, "None of the tests in #{suite_path} specified a base URL.")
end
end
if url
base_url = url.match('https?://[^/]*/?')
else
base_url = nil
end
port = Oats.data['selenium']['ide']['port']
if Oats.data['env']['web']['host']
base_url = 'http://' + Oats.data['env']['web']['host']
else
base_url = base_url[0]
end
# if base_url
# base_url = base_url[0]
# else
# base_url = 'http://' + Oats.data['env']['web']['host']
# $log.warn "Can not determine the base url from [#{url}]. Assuming base url is [#{base_url}]" \
# unless @suite_base_url_signin_type and Oats.data[@suite_base_url_signin_type]["SignIn"]
# end
command = "java -jar \"#{rc_jar_file}\" -port #{port}"
command += " -timeout #{Oats.data['selenium']['ide']['suite_timeout']}" if Oats.data['selenium']['ide']['suite_timeout']
# Don't use profiles when using RC in IDE mode
command += " -firefoxprofileTemplate \"#{$oats_global['firefox_profile_dir']}\"" \
if Oats.data['selenium']['browser_type'] =~ /firefox/ and $oats_global['firefox_profile_dir']
command += " -htmlSuite #{browser} #{base_url} \"#{html_suite_path}\" \"#{result_file}\" 2>&1"
$log.info "Starting Selenium Remote Control: #{command}"
# return # DEBUG
first_rc_try = true
failure_line = nil
catch :end_rc do
2.times do
IO.popen(command) do |io|
while io.gets do
$log.info chomp
if /Selenium is already running on port/ =~ $_
if first_rc_try
io.readlines.each {|line|$log.info line.chomp }
Util.clear_port(Oats.data['selenium']['ide']['port'],$log)
$log.info "Will attempt to restart Selenium RC..."
else
# raise(OatsError, $_, caller[1..3])
raise(OatsError, $_)
throw(:end_rc)
end
first_rc_try = false
elsif /fail/i =~ $_ and /Failed to start: SocketListener/ !~ $_
failure_line = $_
throw(:end_rc)
elsif /exception/i =~ $_ # Like server.SeleniumCommandTimedOutException
failure_line = $_
end
end
end
throw(:end_rc) if first_rc_try
end
end
# pause_val = Oats.data['execution']['ide']['pause_on_exit']
seconds = 999999
pause_val = $oats['selenium']['pause_on_exit']
if not pause_val.integer? or
pause_val <= 0
seconds = nil
elsif pause_val == 1
seconds = nil unless failure_line
elsif pause_val > 0
seconds = pause_val
end
raise(OatsError, "Result file is not readable: #{result_file}") unless File.readable?(result_file)
if seconds
# Need to quote browser path for cygwin because it may have spaces.
begin
timeout(seconds) do
# $stderr.puts "Paused because selenium:pause_on_exit is set to [#{pause_val}]"
# $stderr.puts "PLEASE HIT TO CONTINUE!"
successful = system( '"' +Oats.data['selenium']['ide']['result_browser'] + '" file://'+result_file)
$log.error "Error trying to open results file: #{$?}" \
unless successful or $? == 256
end
rescue Timeout::Error
end
end
TestData.pause_after_error = false
$log.info "Results are at: file://#{result_file}"
raise(OatsTestError, failure_line) if failure_line
end
# Helper method to replace HTML file contents based on oats and test data mappings.
def map_file_contents(oats_data, test_data, file_contents,key_path)
return unless test_data
# $log.debug key_path
if @suite_base_url_signin_type.nil?
@suite_base_url_signin_type = 'Campaign' if key_path == 'root:Campaign:SignIn'
@suite_base_url_signin_type = 'Admin' if key_path == 'root:Admin:SignIn'
# $log.debug "Base URL is set to #{baseUrl}"
end
test_data.each do |key,val|
repVal = oats_data[key]
next if val.nil? or repVal.nil?
if val.class == Hash
map_file_contents( repVal, val, file_contents,key_path + ':' + key)
else
file_contents.gsub!(val, repVal.to_s)
test_data[key] = repVal
end
end
end
# Updates HTML file contents based on current oats_data into test_dir_out
# Returns generated file name or nil if no new file is generated
def regenerate_html(file_in, dir_out, dir_in = dir_out, hash = nil)
basename = File.basename(file_in,'.*')
file_in_absolute = File.expand_path(file_in,dir_in) # get absolute path
unless File.exist?(file_in_absolute)
file_in_absolute = Dir.glob( File.join( $oats['execution']['dir_tests'],
'/**/', file_in.sub(/^(\.\.\/)*/, ''))).first
# file_in = file_in.sub!(/[^\/]*\//,'')
raise(OatsError,"Can not locate IDE test case file: [#{file_in}]") unless file_in_absolute
end
file_in_root = file_in_absolute.sub(/(.*)\..*$/,'\1')
yaml_in = file_in_root + '.yml'
file_out_root = File.join(dir_out, basename)
file_gen = file_out_root +'.gen.html'
yml_out = file_out_root +'.gen.yml'
new_base_name = basename
if File.exist?(file_gen)
new_base_name = File.basename(File.dirname(file_in)) + '_' + new_base_name
file_gen = File.join(dir_out, new_base_name ) +'.gen.html'
yml_out = File.join(dir_out, new_base_name ) +'.gen.yml'
end
if @suite_base_url_signin_type.nil? and @first_test_url.nil?
doc = open(file_in_absolute) { |f| Hpricot(f) }
link = doc.at("link[@rel='selenium.base']")
@first_test_url = link['href'] unless link.nil?
end
unless File.exist?(yaml_in)
return nil if file_in_root == file_out_root
$log.info "Copying [#{file_in_absolute}] to: #{file_gen}]"
FileUtils.cp(file_in_absolute, file_gen)
return basename + '.gen.html'
end
$log.debug "Regenerating [#{file_in_absolute}] into [#{file_gen}] based on [#{yaml_in}]"
file_contents = IO.read(file_in_absolute)
test_data = YAML.load_file(yaml_in)
map_file_contents(Oats.data, test_data, file_contents, 'root')
hash.each { |val, rep_val| file_contents.gsub!(val, rep_val) } if hash
if Oats.data['selenium']['browser_type'] =~ /iexplore/
file_contents.sub!(/(<\/IE-ONLY>.*-->)/,'<-- \1')
file_contents.sub!(/(')
end
File.open( file_gen, 'w' ) { |out| out.print file_contents }
File.open( yml_out, 'w' ) { |out| YAML.dump( test_data, out ) }
basename + '.gen.html'
end
end
end