Ifd_Automation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/Ifd_Automation +30 -0
- data/bin/generate.rb +20 -0
- data/bin/helper.rb +51 -0
- data/features/TestData/testdata.yml +4 -0
- data/features/TestSuite/Login/login.feature +6 -0
- data/features/step_definitions/lib_steps/login_steps.rb +3 -0
- data/features/step_definitions/repositories/ob_login.rb +3 -0
- data/features/support/env.rb +102 -0
- data/features/support/hooks.rb +57 -0
- data/features/support/project_env.rb +51 -0
- data/lib/Ifd_Automation/assertion_steps.rb +96 -0
- data/lib/Ifd_Automation/email_steps.rb +91 -0
- data/lib/Ifd_Automation/javascript_handling_steps.rb +34 -0
- data/lib/Ifd_Automation/lib_file_steps.rb +45 -0
- data/lib/Ifd_Automation/lib_schema_data_steps.rb +110 -0
- data/lib/Ifd_Automation/lib_web_steps.rb +184 -0
- data/lib/Ifd_Automation/lib_webservice_steps.rb +44 -0
- data/lib/Ifd_Automation/methods/IFD_Assertion_methods.rb +206 -0
- data/lib/Ifd_Automation/methods/IFD_Connection.rb +28 -0
- data/lib/Ifd_Automation/methods/IFD_email_methods.rb +16 -0
- data/lib/Ifd_Automation/methods/IFD_webservice.rb +17 -0
- data/lib/Ifd_Automation/methods/core.rb +342 -0
- data/lib/Ifd_Automation/methods/database_methods.rb +25 -0
- data/lib/Ifd_Automation/methods/db_utils.rb +37 -0
- data/lib/Ifd_Automation/methods/error_handling_methods.rb +87 -0
- data/lib/Ifd_Automation/methods/javascript_handling_methods.rb +46 -0
- data/lib/Ifd_Automation/methods/lib_var.rb +59 -0
- data/lib/Ifd_Automation/methods/misc_methods.rb +33 -0
- data/lib/Ifd_Automation/methods/required_files.rb +33 -0
- data/lib/Ifd_Automation/methods/util.rb +168 -0
- data/lib/Ifd_Automation/methods/web_methods.rb +291 -0
- data/lib/Ifd_Automation/methods/web_service_methods.rb +63 -0
- data/lib/Ifd_Automation/version.rb +5 -0
- data/lib/Ifd_Automation.rb +1 -0
- metadata +439 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
require_relative 'methods/required_files'
|
2
|
+
#====================================
|
3
|
+
# INTERACTION STEPS
|
4
|
+
#====================================
|
5
|
+
# Step used to execute a SQL script on a specific schema
|
6
|
+
And /^I run sql script "([^\"]*)" on "([^\"]*)" schema$/ do |script, schema|
|
7
|
+
begin
|
8
|
+
sql = "#{script}"
|
9
|
+
DatabaseMethods.execute_select(schema, sql)
|
10
|
+
DatabaseMethods.close_connection(schema)
|
11
|
+
ensure
|
12
|
+
end
|
13
|
+
end
|
14
|
+
# Step used to execute SQL script from SQL file on specific schema
|
15
|
+
Given /^I run sql script from file "([^\"]*)" on "([^\"]*)" schema$/ do |sql_script, schema|
|
16
|
+
if sql_script != nil and sql_script != ""
|
17
|
+
begin
|
18
|
+
File.readlines($sql_dir + sql_script).each do |line|
|
19
|
+
if line.nil? || line =~ /^\s*\n*--/
|
20
|
+
# puts "\nSQL: " + line;
|
21
|
+
next;
|
22
|
+
end
|
23
|
+
line = line.strip();
|
24
|
+
line = line[0..-2];
|
25
|
+
#puts "\nSQL: " + line;
|
26
|
+
DatabaseMethods.execute_select(schema, line)
|
27
|
+
sleep(1);
|
28
|
+
end
|
29
|
+
DatabaseMethods.close_connection(schema)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
#====================================
|
34
|
+
# VERIFICATION STEPS
|
35
|
+
#====================================
|
36
|
+
# Step used to check if data exists in database or not
|
37
|
+
Then /^I should ( not)? see data in table "([^\"]*)" on "([^\"]*)" schema in database as following record:$/ do |negative, table, schema, table_data|
|
38
|
+
records = Util.read_table_data_from_steps_with_header(table_data.raw)
|
39
|
+
records = JSON.parse(JSON.generate(records))
|
40
|
+
puts records
|
41
|
+
records.each { |values|
|
42
|
+
table_type_obj = Util.generate_condition_statement(values)
|
43
|
+
# puts table_type_obj
|
44
|
+
begin
|
45
|
+
sql= "select count(*) from #{schema}.#{table} where #{table_type_obj}"
|
46
|
+
rs = DatabaseMethods.execute_select(schema, sql)
|
47
|
+
# puts sql
|
48
|
+
obj_array = Array.new
|
49
|
+
rs.each { |row|
|
50
|
+
row.each_pair { |col, value|
|
51
|
+
assert(false) if negative.nil? && value == 0 || !negative.nil? && value == 1
|
52
|
+
}
|
53
|
+
}
|
54
|
+
ensure
|
55
|
+
DatabaseMethods.close_connection(schema)
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
# Step used to check if data exists in database or not with condition in file
|
60
|
+
Then /^I should ( not)? see data in schema "(.*)" database with SQL query in file "(.*)"$/ do |negative, schema, file|
|
61
|
+
sql = File.read($test_data_dir + file)
|
62
|
+
filepath = ($test_data_dir + file)
|
63
|
+
if File.exist?(filepath)
|
64
|
+
begin
|
65
|
+
rs = DatabaseMethods.execute_select(schema, sql)
|
66
|
+
obj_array = Array.new
|
67
|
+
rs.each { |row|
|
68
|
+
row.each_pair { |col, value|
|
69
|
+
assert(false) if negative.nil? && value == 0 || !negative.nil? && value == 1
|
70
|
+
}
|
71
|
+
}
|
72
|
+
ensure
|
73
|
+
DatabaseMethods.close_connection(schema)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
raise "*** ERROR: Please check #{filepath} exists."
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Step used to get data from database
|
81
|
+
Then /^I get "(.*)" data from table "([^\"]*)" on "([^\"]*)" schema in database as following record:$/ do |value, table, schema, table_data|
|
82
|
+
records = Util.read_table_data_from_steps_with_header(table_data.raw)
|
83
|
+
records = JSON.parse(JSON.generate(records))
|
84
|
+
records.each { |values|
|
85
|
+
table_type_obj = Util.generate_condition_statement(values)
|
86
|
+
begin
|
87
|
+
sql= "select #{value} from #{table} where #{table_type_obj}"
|
88
|
+
sql_count= "select count(*) from #{table} where #{table_type_obj}"
|
89
|
+
rs = DatabaseMethods.execute_select(schema, sql)
|
90
|
+
record_result= DatabaseMethods.execute_select(schema, sql_count)
|
91
|
+
record_result.each { |rows|
|
92
|
+
rows.each_pair { |cols, values|
|
93
|
+
@@value_count= values
|
94
|
+
}
|
95
|
+
}
|
96
|
+
if @@value_count == 0
|
97
|
+
puts ("***WARNING: NOT FOUND #{table_type_obj} in #{schema}")
|
98
|
+
|
99
|
+
else
|
100
|
+
rs.each { |row|
|
101
|
+
row.each_pair { |cols, values|
|
102
|
+
$result=values
|
103
|
+
}
|
104
|
+
}
|
105
|
+
end
|
106
|
+
ensure
|
107
|
+
DatabaseMethods.close_connection(schema)
|
108
|
+
end
|
109
|
+
}
|
110
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative 'methods/required_files'
|
2
|
+
# Navigate to a particular page
|
3
|
+
Given(/^I am on the "([^"]*)" page$/) do |page|
|
4
|
+
execute_openbrowser(page)
|
5
|
+
end
|
6
|
+
|
7
|
+
#Navigating to the login page
|
8
|
+
Given /^I am on Login Page$/ do
|
9
|
+
execute_openbrowser($_CFWEB['Page Address'])
|
10
|
+
end
|
11
|
+
|
12
|
+
# Wait for the specific time
|
13
|
+
When /^I wait for (\d+) seconds$/ do |second|
|
14
|
+
sleep(second.to_i)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Finds a button or link by id, text or value and clicks it
|
18
|
+
And /^I click on "([^\"]*)"$/ do |object|
|
19
|
+
execute_click(object)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Finds and clicks it with JS
|
23
|
+
And /^I move mouse to element "([^\"]*)" then click$/ do |object|
|
24
|
+
execute_mousehoverandclick(object)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Fill in a text box or text area with a value
|
28
|
+
And /^I set text on "(.*?)" with "(.*?)"$/ do |object, text|
|
29
|
+
text = var_collect(text)
|
30
|
+
text = replace_pipe(text)
|
31
|
+
execute_settext(object, text)
|
32
|
+
end
|
33
|
+
|
34
|
+
# set state for check box, combo box
|
35
|
+
And /^I set state on "(.*?)" with "(.*?)"$/ do |object, state|
|
36
|
+
execute_setstate(object, state)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Input data to text box, this function support in case user want to input data into many text boxes on the same time
|
40
|
+
When /^I input data to web form with following values:$/ do |value|
|
41
|
+
records = Util.read_table_data_from_steps_with_header(value.raw)
|
42
|
+
records = JSON.parse(JSON.generate(records))
|
43
|
+
records.each { |rows|
|
44
|
+
rows.each { |col, val|
|
45
|
+
step %{I set text on "#{col}" with "#{val}"}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
When /^I run the following steps?:$/ do |steps_table|
|
51
|
+
steps = steps_table.raw.flatten
|
52
|
+
steps.each do |step|
|
53
|
+
call_step step
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
When /^I click on following elements:$/ do |object|
|
58
|
+
object.raw.each do |lines|
|
59
|
+
lines.each do |line|
|
60
|
+
step %{I click on "#{line}"}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Then /^I run following steps in iframe (index|name) (.*):$/ do |frame_type, frame, step_table|
|
66
|
+
case frame_type.to_sym
|
67
|
+
when :index
|
68
|
+
steps = step_table.raw.flatten
|
69
|
+
browser = page.driver.browser
|
70
|
+
browser.switch_to.frame(frame.to_i)
|
71
|
+
steps.each do |step|
|
72
|
+
call_step step
|
73
|
+
end
|
74
|
+
browser.switch_to.default_content
|
75
|
+
when :name
|
76
|
+
browser = page.driver.browser
|
77
|
+
browser.switch_to.frame(frame.to_s)
|
78
|
+
steps.each do |step|
|
79
|
+
call_step step
|
80
|
+
end
|
81
|
+
browser.switch_to.default_content
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# get text for object
|
86
|
+
And /^I get text on "(.*?)" then store it into file "(.*)"$/ do |object, file_name|
|
87
|
+
$text = execute_gettext(object)
|
88
|
+
open($test_data_dir+file_name, 'a+') do |f|
|
89
|
+
f << $text + "\n"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Fill in a text box or text area with a value from $test_data_dir file
|
94
|
+
And /^I set text on "(.*?)" with value from file "(.*)"$/ do |object, file_name|
|
95
|
+
expected_file= ($test_data_dir + file_name)
|
96
|
+
if File.exist?(expected_file)
|
97
|
+
# data_file = File.read(expected_file)
|
98
|
+
data_file = read_file(expected_file)
|
99
|
+
execute_settext(object, data_file)
|
100
|
+
# data_file.each_line do |line|
|
101
|
+
# execute_settext(object, line)
|
102
|
+
# end
|
103
|
+
else
|
104
|
+
raise "*** ERROR: File #{file_name} is not existed!"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Upload new file windows
|
109
|
+
When /^I click on "(.*?)" to upload file "(.*?)"$/ do |object, file_name|
|
110
|
+
execute_click_to_upload(object, file_name)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Drag mouse hover on element
|
114
|
+
When /^I move mouse to element "(.*?)"$/ do |element|
|
115
|
+
execute_hover_mouse_on(element)
|
116
|
+
end
|
117
|
+
|
118
|
+
And /^I click on "(.*?)" and wait (\d+) seconds$/ do |object, seconds|
|
119
|
+
execute_click(object)
|
120
|
+
sleep(seconds.to_i)
|
121
|
+
end
|
122
|
+
|
123
|
+
And /^I drag object "(.*?)" to "(.*?)"$/ do |from_object, object|
|
124
|
+
execute_drag_to_new_object(from_object, object)
|
125
|
+
end
|
126
|
+
|
127
|
+
# And /^I test$/ do
|
128
|
+
# es_data = File.read("C:/Users/Anh Pham/Desktop/testdata_ES_ruby.txt")
|
129
|
+
# data = JSON.parse(es_data)
|
130
|
+
# data['hits']['hits'].each do |child|
|
131
|
+
# replaced_value = child['_source']['timestamp'].gsub("Oct", "2015-10-").gsub!(/\s+/, "").insert(10, 'T')+ ".112Z"
|
132
|
+
# new_value = child.to_s.gsub(child['_source']['@timestamp'], "\""+replaced_value+"\"")
|
133
|
+
# open("D:/IFD Project Automation/Master Branch/features/MYM/Data/test.txt", 'a+') do |f|
|
134
|
+
# f << new_value + "\n"
|
135
|
+
# end
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
|
139
|
+
And /^I type to "(.*)" key is "(.*?)"$/ do |object, keys|
|
140
|
+
keys = var_collect(keys)
|
141
|
+
execute_sendkeys(object, keys)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Click on ID of link or text of link
|
145
|
+
When /^I click on "([^\"]*)" link$/ do |link|
|
146
|
+
click_link link
|
147
|
+
end
|
148
|
+
|
149
|
+
# Upload file
|
150
|
+
When /^I attach the file "(.*)" to "(.*)"$/ do |filename, field|
|
151
|
+
filepath = File.join($base_dir, filename)
|
152
|
+
if filepath.match(/^C:\//)
|
153
|
+
filepath.gsub!(/\//, '\\')
|
154
|
+
end
|
155
|
+
attach_file(field, filepath)
|
156
|
+
end
|
157
|
+
|
158
|
+
# double click on web element
|
159
|
+
Then(/^I double click on element "(.*?)"$/) do |element|
|
160
|
+
double_click(element)
|
161
|
+
end
|
162
|
+
|
163
|
+
# step to resize browser
|
164
|
+
Then(/^I resize browser window size to width (\d+) and height (\d+)$/) do |width, heigth|
|
165
|
+
resize_browser(width, heigth)
|
166
|
+
end
|
167
|
+
|
168
|
+
# step to maximize browser
|
169
|
+
Then(/^I maximize browser window$/) do
|
170
|
+
maximize_browser
|
171
|
+
end
|
172
|
+
|
173
|
+
Then(/^I switch to window having title "(.*?)"$/) do |window_title|
|
174
|
+
switch_to_window_by_title window_title
|
175
|
+
end
|
176
|
+
|
177
|
+
Then(/^I take screenshot$/) do
|
178
|
+
take_screenshot
|
179
|
+
end
|
180
|
+
|
181
|
+
# steps to scroll web page to top or end
|
182
|
+
Then(/^I scroll to (top|end) of page$/) do |to|
|
183
|
+
scroll_page(to)
|
184
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require_relative 'methods/required_files'
|
3
|
+
# Send POST XML request with data in $test_data_dir
|
4
|
+
When /^I send a POST XML request to "(.*?)" with the following file "(.*?)"$/ do |type, file|
|
5
|
+
file = Util.bind_with_dyn_vars(file)
|
6
|
+
url = Util.bind_with_dyn_vars($WS_URL)
|
7
|
+
# url=$WS_URL
|
8
|
+
data = File.read($test_data_dir + file)
|
9
|
+
$result=IFD_WS.send_XML_post_webservice(url,type,data)
|
10
|
+
end
|
11
|
+
# Verify XML response with data is table format
|
12
|
+
Then /^The XML response of "(.*)" should be the following:$/ do |xpath,table|
|
13
|
+
data = table.raw
|
14
|
+
expected_result=data[0][0]
|
15
|
+
data = Nokogiri::XML.parse($result).remove_namespaces!
|
16
|
+
actual_result= data.xpath(xpath).to_s
|
17
|
+
# puts expected_result.to_s
|
18
|
+
puts actual_result.to_s
|
19
|
+
# Do assert with the different size of xml
|
20
|
+
IFD_Assertion.assert_string_equal(expected_result,actual_result)
|
21
|
+
end
|
22
|
+
# Send POST XML request with template in $test_data_dir and condition is table format
|
23
|
+
When /^I send a POST XML request to "(.*?)" with file template "(.*?)" and following conditions:$/ do |type, file, data_table|
|
24
|
+
file = Util.bind_with_dyn_vars(file)
|
25
|
+
url = Util.bind_with_dyn_vars($WS_URL)
|
26
|
+
data = File.read($test_data_dir + file)
|
27
|
+
raw_data = JSON.parse(JSON.generate(data_table))
|
28
|
+
header = raw_data[0]
|
29
|
+
value = raw_data[1]
|
30
|
+
i = 0
|
31
|
+
header.zip(value).each do |headers, values|
|
32
|
+
value_condition = Nokogiri::XML.parse(data).xpath("//"+headers).to_s
|
33
|
+
tag_value= value_condition[/.*\>(.*?)</, 1]
|
34
|
+
$new_value = value_condition.gsub(tag_value, values)
|
35
|
+
if i>0 then
|
36
|
+
$data_new= $data_new.gsub(value_condition, $new_value)
|
37
|
+
else
|
38
|
+
$data_new=data.gsub(value_condition, $new_value)
|
39
|
+
end
|
40
|
+
i = i+1
|
41
|
+
end
|
42
|
+
$result=IFD_WS.send_XML_post_webservice(url, type, $data_new)
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
include Test::Unit::Assertions
|
2
|
+
class IFD_Assertion
|
3
|
+
#Assert two files, rows not in order and REMOVE 1 COLUMN OF ID
|
4
|
+
def self.do_assertion_csv_tab_non_order(expected_obj, actual_obj)
|
5
|
+
for i in (1..expected_obj.length - 1)
|
6
|
+
expected_row = expected_obj[i].drop(1).to_s.split("\t")
|
7
|
+
found = false
|
8
|
+
for j in (1..actual_obj.length - 1)
|
9
|
+
actual_row = actual_obj[j].drop(1).to_s.split("\t")
|
10
|
+
if (expected_row == actual_row)
|
11
|
+
found = true
|
12
|
+
break
|
13
|
+
end
|
14
|
+
end
|
15
|
+
assert(found, "Expected Record: [#{expected_obj[i].to_s}] is not included in reporting file")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Assert 2 values
|
20
|
+
def self.reg_compare sActual, regValue, isSpecialChar=false
|
21
|
+
begin
|
22
|
+
if !isSpecialChar
|
23
|
+
sActual = sActual.strip
|
24
|
+
regValue = regValue.strip.gsub("[", "\\[").gsub("]", "\\]").gsub("(", "\\(").gsub(")", "\\)").gsub(">", "\\>")
|
25
|
+
end
|
26
|
+
rescue StandardError => myStandardError
|
27
|
+
put_log "\n>>> Error: #{myStandardError}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# put_log "\nsActual:#{sActual}, regValue:#{regValue}"
|
31
|
+
if ((sActual.nil? and regValue.nil?) or (!sActual.nil? and sActual.empty? and !regValue.nil? and regValue.empty?))
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
if ((sActual.nil? and !regValue.nil?) or (!sActual.nil? and regValue.nil?))
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
if (!sActual.nil? and !sActual.empty?)
|
40
|
+
sCookActual = sActual.gsub(/\n|\r/, " ")
|
41
|
+
if (sCookActual == regValue or (isSpecialChar and sCookActual.include? regValue) or (!isSpecialChar and sCookActual =~ /^.*#{regValue}.*$/))
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.do_assertion_json(expected_obj, actual_obj, options = {})
|
50
|
+
# puts "\n\n actual_obj.class: #{actual_obj.class}"
|
51
|
+
# puts "\n\n expected_obj.class: #{expected_obj.class}"
|
52
|
+
|
53
|
+
if expected_obj.kind_of? Hash
|
54
|
+
# if options['isIncludedAssertion'].nil? or options['isIncludedAssertion'] == false
|
55
|
+
# do_assertion(expected_obj.keys.size, actual_obj.keys.size)
|
56
|
+
# end
|
57
|
+
expected_obj.keys.each do |key|
|
58
|
+
# puts "\n\n key: #{key}"
|
59
|
+
# puts "\n\n value: #{expected_obj[key]}"
|
60
|
+
# puts "\n\n value: #{actual_obj[key]}"
|
61
|
+
if actual_obj[key].nil?
|
62
|
+
raise "[%s] expected [%s] but actual value was nil." % [key, expected_obj[key].to_s]
|
63
|
+
else
|
64
|
+
IFD_Assertion.do_assertion_json(expected_obj[key], actual_obj[key], options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
elsif expected_obj.kind_of? Array
|
68
|
+
if options['isIncludedAssertion'].nil? or options['isIncludedAssertion'] == false
|
69
|
+
IFD_Assertion.do_assertion_json(expected_obj.size, actual_obj.size)
|
70
|
+
end
|
71
|
+
for i in (0..expected_obj.length-1)
|
72
|
+
IFD_Assertion.do_assertion_json(expected_obj[i], actual_obj[i], options)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
begin
|
76
|
+
IFD_Assertion.assert_string_equal(expected_obj.to_s, actual_obj.to_s)
|
77
|
+
rescue => e
|
78
|
+
raise("Assert fail. \n\n Expected: '#{expected_obj}' \n\n Got: '#{actual_obj}'. Detail info: #{e.message}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.assert_string_contain(expected, actual)
|
84
|
+
unless (actual.to_s).include? (expected.to_s)
|
85
|
+
raise ("*** ASSERTION ERROR: \nExpected: #{expected}. \nGot: #{actual}.")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.assert_string_equal(expected, actual)
|
90
|
+
if expected.to_s != actual.to_s
|
91
|
+
raise ("*** ASSERTION ERROR: \nExpected: #{expected}. \nGot: #{actual}.")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Method to find difference between images
|
97
|
+
def self.does_images_similar?(actual_img_access_type, actual_img_access_name, excp_img_access_type, excp_img_access_name)
|
98
|
+
if !compare_image(actual_img_access_type, actual_img_access_name, excp_img_access_type, excp_img_access_name)
|
99
|
+
raise TestCaseFailed, 'Actual image is different from expected image'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Method to compare two images
|
104
|
+
# param 1 : String : Locator type (id, name, class, xpath, css, url)
|
105
|
+
# param 2 : String : Locator value
|
106
|
+
# param 3 : String : Locator type (id, name, class, xpath, css, url, image_name)
|
107
|
+
# param 4 : String : Locator value
|
108
|
+
def self.compare_image(actual_img_access_type, actual_img_access_name, excp_img_access_type, excp_img_access_name)
|
109
|
+
if actual_img_access_type == 'url'
|
110
|
+
actual_img_url = actual_img_access_name
|
111
|
+
elsif actual_img_access_type == 'image_name'
|
112
|
+
actual_img_url = $test_data_dir + '/actual_images/' + actual_img_access_name
|
113
|
+
else
|
114
|
+
actual_img_url = get_element_attribute(actual_img_access_type, actual_img_access_name, 'src')
|
115
|
+
end
|
116
|
+
|
117
|
+
if excp_img_access_type == 'url'
|
118
|
+
expected_img_url = excp_img_access_name
|
119
|
+
elsif excp_img_access_type == 'image_name'
|
120
|
+
expected_img_url = $test_data_dir + '/expected_images/' + excp_img_access_name
|
121
|
+
else
|
122
|
+
expected_img_url = get_element_attribute(excp_img_access_type, excp_img_access_name, 'src')
|
123
|
+
end
|
124
|
+
|
125
|
+
# replace 'https' with 'http' from actual image url
|
126
|
+
if actual_img_url.include? 'https'
|
127
|
+
actual_img_url['https'] = 'http'
|
128
|
+
end
|
129
|
+
|
130
|
+
# replace 'https' with 'http' from expected image url
|
131
|
+
if expected_img_url.include? 'https'
|
132
|
+
expected_img_url['https'] = 'http'
|
133
|
+
end
|
134
|
+
|
135
|
+
if expected_img_url.include? '.png'
|
136
|
+
image_type = 'png'
|
137
|
+
else
|
138
|
+
image_type = 'jpg'
|
139
|
+
end
|
140
|
+
|
141
|
+
# Storing actual image locally
|
142
|
+
open($test_data_dir + '/actual_images/actual_image.' + image_type, 'wb') do |file|
|
143
|
+
file << open(actual_img_url).read
|
144
|
+
end
|
145
|
+
|
146
|
+
if actual_img_access_type == 'url'
|
147
|
+
actual_img_url = $test_data_dir + '/actual_images/actual_image.' + image_type
|
148
|
+
end
|
149
|
+
|
150
|
+
# Storing Expected image locally
|
151
|
+
if excp_img_access_type != 'image_name'
|
152
|
+
open($test_data_dir + '/expected_images/expected_image.' + image_type, 'wb') do |file|
|
153
|
+
file << open(expected_img_url).read
|
154
|
+
end
|
155
|
+
expected_img_url = $test_data_dir + '/expected_images/expected_image.' + image_type
|
156
|
+
end
|
157
|
+
|
158
|
+
# Verify image extension and call respective compare function
|
159
|
+
if image_type == 'png'
|
160
|
+
return compare_png_images(expected_img_url, actual_img_url)
|
161
|
+
end
|
162
|
+
|
163
|
+
compare_jpeg_images(expected_img_url, actual_img_url)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Comparing jpg images
|
167
|
+
def self.compare_jpeg_images(expected_img_url, actual_img_url)
|
168
|
+
if open(expected_img_url).read == open(actual_img_url).read
|
169
|
+
return true
|
170
|
+
else
|
171
|
+
puts 'Difference in images'
|
172
|
+
return false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Comparing png images
|
177
|
+
def self.compare_png_images(expected_img_url, actual_img_url)
|
178
|
+
images = [
|
179
|
+
ChunkyPNG::Image.from_file(expected_img_url),
|
180
|
+
ChunkyPNG::Image.from_file(actual_img_url)
|
181
|
+
]
|
182
|
+
|
183
|
+
diff = []
|
184
|
+
|
185
|
+
images.first.height.times do |y|
|
186
|
+
images.first.row(y).each_with_index do |pixel, x|
|
187
|
+
diff << [x, y] unless pixel == images.last[x, y]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if diff.length != 0
|
192
|
+
puts "\npixels (total): #{images.first.pixels.length}"
|
193
|
+
puts "pixels changed: #{diff.length}"
|
194
|
+
puts "pixels changed (%): #{(diff.length.to_f / images.first.pixels.length) * 100}%"
|
195
|
+
|
196
|
+
x, y = diff.map { |xy| xy[0] }, diff.map { |xy| xy[1] }
|
197
|
+
images.last.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0, 255, 0))
|
198
|
+
cur_time = Time.now.strftime('%Y%m%d%H%M%S%L')
|
199
|
+
images.last.save($test_data_dir + "/image_difference/difference_#{cur_time}.png")
|
200
|
+
|
201
|
+
puts "\nDifference between images saved as : difference_#{cur_time}.png\n"
|
202
|
+
return false
|
203
|
+
end
|
204
|
+
true
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
require 'tiny_tds'
|
3
|
+
|
4
|
+
class IFD_Connections
|
5
|
+
# Open the MYSQL connection to specific schema
|
6
|
+
def self.get_mysql_db_connection(schema)
|
7
|
+
begin
|
8
|
+
# puts ("Connecting to database...");
|
9
|
+
data_source_schema = schema.downcase
|
10
|
+
return Mysql2::Client.new(host: $data_source_url, username: $data_source_username, password: $data_source_password,database:data_source_schema);
|
11
|
+
rescue Exception => e
|
12
|
+
raise "Cannot connect to database [username: %s; password: %s, dbUrl: %s, dbName: %s] with error %s" %
|
13
|
+
[$data_source_username, $data_source_password, $data_source_url,data_source_schema, e.message]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Open the SQL Server connection to specific schema
|
18
|
+
def self.get_sql_server_db_connection(schema)
|
19
|
+
begin
|
20
|
+
# puts ("Connecting to database...");
|
21
|
+
data_source_schema = schema.downcase
|
22
|
+
return TinyTds::Client.new(dataserver: $data_source_url, username: $data_source_username, password: $data_source_password, database:data_source_schema);
|
23
|
+
rescue Exception => e
|
24
|
+
raise "Cannot connect to database [username: %s; password: %s, dbUrl: %s, dbName: %s] with error %s" %
|
25
|
+
[$data_source_username, $data_source_password, $data_source_url,data_source_schema, e.message]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'mail'
|
2
|
+
require 'email_spec'
|
3
|
+
# include EmailSpec::Helpers
|
4
|
+
# include EmailSpec::Matcher
|
5
|
+
class IFD_Email < ActionMailer::Base
|
6
|
+
def self.send_email(to_address, subject, body_email)
|
7
|
+
include Mail::Matchers
|
8
|
+
# Mail::TestMailer.deliveries.clear
|
9
|
+
Mail.deliver do
|
10
|
+
from $SEND_EMAIL_USERNAME
|
11
|
+
to to_address
|
12
|
+
subject subject
|
13
|
+
body body_email
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class IFD_WS
|
2
|
+
|
3
|
+
def self.send_XML_post_webservice(host,type,data)
|
4
|
+
url = "#{host}/#{type}"
|
5
|
+
puts url
|
6
|
+
WebServiceMethods.send_XML_post_request(url,data)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.send_get_MYM_webservice(host,type,data)
|
10
|
+
url = "#{host}/#{type}?#{data}"
|
11
|
+
WebServiceMethods.send_get_request(url)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|