Resolves tdf#129295 - Hyperlink Text below URL
[LibreOffice.git] / uitest / loginterpreter.py
blobe84d9a0ed7e1af4117d64677b7a3c6b843163fa1
1 #!/usr/bin/env python3
2 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
4 # This file is part of the LibreOffice project.
6 # This Source Code Form is subject to the terms of the Mozilla Public
7 # License, v. 2.0. If a copy of the MPL was not distributed with this
8 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 import os
12 import sys
13 import argparse
15 def parse_line(line):
16 """
17 This function parses a line from log file
18 and returns the parsed values as a python dictionary
19 """
20 if (line == ""):
21 return
22 dict = {}
23 if "{" in line:
24 start_index_of_parameters = line.find("{")
25 end_index_of_parameters = line.find("}") + 1
26 parameters = line[start_index_of_parameters:end_index_of_parameters]
27 if parameters != "":
28 dict["parameters"] = parameters
29 line = line[:start_index_of_parameters-1]
30 word_list = line.split()
31 dict["keyword"] = word_list[0]
33 for index in range(1,len(word_list)):
34 key, val = word_list[index].split(":",1)
35 dict[key] = val
36 return dict
38 def parse_args():
39 """
40 This function parses the command-line arguments
41 to get the input and output file details
42 """
43 parser = argparse.ArgumentParser(description = "Generate a UI test file from log")
44 parser.add_argument("input_address", type = str, help = "The log file address")
45 parser.add_argument("output_address", type = str, help = "The test file address")
46 parser.add_argument("-d", "--document", metavar = "", help = "Address of the document to be opened")
47 args = parser.parse_args()
48 return args
50 def get_log_file(input_address):
51 try:
52 with open(input_address) as f:
53 content = f.readlines()
54 except IOError as err:
55 print("IO error: {0}".format(err))
56 print("Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions")
57 sys.exit(1)
59 content = [x.strip() for x in content if not x.startswith("Action on element")]
60 return content
62 def initiate_test_generation(address):
63 try:
64 f = open(address,"w")
65 except IOError as err:
66 print("IO error: {0}".format(err))
67 print("Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions")
68 sys.exit(1)
69 initial_text = \
70 "# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-\n\n" + \
71 "from uitest.framework import UITestCase\n" + \
72 "from libreoffice.uno.propertyvalue import mkPropertyValues\n" + \
73 "import importlib\n\n" + \
74 "class TestClass(UITestCase):\n" + \
75 " def test_function(self):\n"
76 f.write(initial_text)
77 return f
79 def get_coupling_type(line1, line2):
80 """
81 This function checks if two consecutive lines of log file
82 refer to the same event
83 """
84 action_dict1 = parse_line(line1)
85 action_dict2 = parse_line(line2)
87 if action_dict1["keyword"] == "CommandSent" and \
88 action_dict2["keyword"] == "ModalDialogExecuted":
89 return "COMMAND_MODAL_COUPLE"
91 elif action_dict1["keyword"] == "CommandSent" and \
92 action_dict2["keyword"] == "ModelessDialogConstructed":
93 return "COMMAND_MODELESS_COUPLE"
95 elif action_dict1["keyword"] == "ButtonUIObject" and \
96 action_dict2["keyword"] == "DialogClosed":
97 return "BUTTON_DIALOGCLOSE_COUPLE"
99 elif "parameters" in action_dict1 and \
100 "KEYCODE" in action_dict1["parameters"] and \
101 action_dict2["keyword"] == "CommandSent":
102 return "REDUNDANT_COUPLE"
104 return "NOT_A_COUPLE"
106 def check_app_starting_action(action_dict):
107 app_starter_button_ids = \
108 set(["draw_all", "impress_all", "calc_all" , "writer_all", "database_all", "math_all"])
110 if action_dict["keyword"] == "ButtonUIObject" and action_dict["Action"] == "CLICK" and \
111 action_dict["Id"] in app_starter_button_ids:
112 return True
113 return False
115 def get_test_line_from_one_log_line(log_line):
116 action_dict = parse_line(log_line)
117 test_line = " "
118 if action_dict["keyword"].endswith("UIObject"):
119 parent = action_dict["Parent"]
120 if (check_app_starting_action(action_dict)):
121 test_line +=\
122 "MainDoc = self.ui_test.create_doc_in_start_center(\"" + \
123 action_dict["Id"][:-4] +"\")\n MainWindow = " + \
124 "self.xUITest.getTopFocusWindow()\n"
125 return test_line
126 else:
127 if (parent == ""):
128 parent = "MainWindow"
129 test_line += \
130 action_dict["Id"] + " = " + parent + ".getChild(\"" + \
131 action_dict["Id"] + "\")\n " + \
132 action_dict["Id"] + ".executeAction(\"" + \
133 action_dict["Action"] + "\""
134 if "parameters" in action_dict:
135 test_line += ", mkPropertyValues(" + \
136 action_dict["parameters"] + "))\n"
137 else:
138 test_line += ",tuple())\n"
139 return test_line
140 elif action_dict["keyword"] == "CommandSent":
141 if "parameters" not in action_dict:
142 test_line += "self.xUITest.executeCommand(\"" + \
143 action_dict["Name"] + "\")\n"
144 return test_line
145 else:
146 test_line += "self.xUITest.executeCommandWithParameters(\"" + \
147 action_dict["Name"] + "\", mkPropertyValues(" + action_dict["parameters"] + \
148 "))\n"
149 return test_line
150 elif action_dict["keyword"] == "ModalDialogExecuted" or \
151 action_dict["keyword"] == "ModelessDialogConstructed":
152 test_line += action_dict["Id"] + " = " + "self.xUITest.getTopFocusWindow()\n"
153 return test_line
155 return ""
157 def get_test_line_from_two_log_lines(log_line1,log_line2):
158 coupling_type = get_coupling_type(log_line1, log_line2)
159 action_dict1 = parse_line(log_line1)
160 action_dict2 = parse_line(log_line2)
161 test_line = " "
162 if coupling_type == "COMMAND_MODAL_COUPLE":
163 test_line += \
164 "self.ui_test.execute_dialog_through_command(\"" + \
165 action_dict1["Name"] + "\")\n " + \
166 action_dict2["Id"] + " = self.xUITest.getTopFocusWindow()\n"
167 elif coupling_type == "COMMAND_MODELESS_COUPLE":
168 test_line += \
169 "self.ui_test.execute_modeless_dialog_through_command(\"" + \
170 action_dict1["Name"] + "\")\n " + \
171 action_dict2["Id"] + " = self.xUITest.getTopFocusWindow()\n"
172 elif coupling_type == "BUTTON_DIALOGCLOSE_COUPLE":
173 test_line += \
174 action_dict1["Id"] + " = " + action_dict1["Parent"] + ".getChild(\"" + \
175 action_dict1["Id"] + "\")\n self.ui_test.close_dialog_through_button(" + \
176 action_dict1["Id"] + ")\n"
177 return test_line
179 def main():
180 args = parse_args()
181 log_lines = get_log_file(args.input_address)
182 output_stream = initiate_test_generation(args.output_address)
183 if args.document is not None:
184 output_line = " pathmodule = importlib.import_module(\"uitest.path\")\n" + \
185 " doc_path = pathmodule.get_srcdir_url() + \"" + args.document + "\"\n" + \
186 " MainDoc = self.ui_test.load_file(doc_path)\n" + \
187 " MainWindow = self.xUITest.getTopFocusWindow()\n"
188 output_stream.write(output_line)
189 line_number = 0
190 while line_number < len(log_lines):
191 if line_number == len(log_lines)-1 or \
192 get_coupling_type(log_lines[line_number],log_lines[line_number + 1]) == "NOT_A_COUPLE":
193 test_line = get_test_line_from_one_log_line(log_lines[line_number])
194 output_stream.write(test_line)
195 line_number += 1
196 elif get_coupling_type(log_lines[line_number],log_lines[line_number + 1]) == "REDUNDANT_COUPLE":
197 line_number += 1
198 else:
199 test_line = get_test_line_from_two_log_lines(log_lines[line_number],log_lines[line_number + 1])
200 output_stream.write(test_line)
201 line_number += 2
202 output_stream.write(" self.ui_test.close_doc()")
203 output_stream.write("\n\n# vim: set shiftwidth=4 softtabstop=4 expandtab:")
204 output_stream.close()
206 if __name__ == '__main__':
207 main()
209 # vim: set shiftwidth=4 softtabstop=4 expandtab: