diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-05-13 13:21:33 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-05-14 18:04:10 +0100 |
commit | 80ca4f00f82cd2f58fe5cda38c8cc5a719c887b6 (patch) | |
tree | f2d5a130213c37b8aed1fb07fecf46eb9e5e1a13 /bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py | |
parent | 23f5b009e0ebf59cfcc9ae90a1084468fc88e42f (diff) | |
download | poky-80ca4f00f82cd2f58fe5cda38c8cc5a719c887b6.tar.gz |
bitbake: toaster/contrib: adding TTS squashed patch
In order to move the Toaster Test System in Toaster itself,
we create a contrib directory.
The TTS is added as a squashed patch with no history.
It contains code contributed by Ke Zou <ke.zou@windriver.com>.
(Bitbake rev: 7d24fea2b5dcaac6add738b6fb4700d698824286)
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py')
-rwxr-xr-x | bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py | 1924 |
1 files changed, 1924 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py b/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py new file mode 100755 index 0000000000..c03a937b89 --- /dev/null +++ b/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py | |||
@@ -0,0 +1,1924 @@ | |||
1 | #!/usr/bin/python | ||
2 | # Copyright | ||
3 | |||
4 | # DESCRIPTION | ||
5 | # This is toaster automation base class and test cases file | ||
6 | |||
7 | # History: | ||
8 | # 2015.03.09 inital version | ||
9 | # 2015.03.23 adding toaster_test.cfg, run_toastertest.py so we can run case by case from outside | ||
10 | |||
11 | # Briefs: | ||
12 | # This file is comprised of 3 parts: | ||
13 | # I: common utils like sorting, getting attribute.. etc | ||
14 | # II: base class part, which complies with unittest frame work and | ||
15 | # contains class selenium-based functions | ||
16 | # III: test cases | ||
17 | # to add new case: just implement new test_xxx() function in class toaster_cases | ||
18 | |||
19 | # NOTES for cases: | ||
20 | # case 946: | ||
21 | # step 6 - 8 needs to be observed using screenshots | ||
22 | # case 956: | ||
23 | # step 2 - 3 needs to be run manually | ||
24 | |||
25 | import unittest, time, re, sys, getopt, os, logging, string, errno, exceptions | ||
26 | import shutil, argparse, ConfigParser, platform | ||
27 | from selenium import webdriver | ||
28 | from selenium.common.exceptions import NoSuchElementException | ||
29 | from selenium import selenium | ||
30 | from selenium.webdriver.common.by import By | ||
31 | from selenium.webdriver.common.keys import Keys | ||
32 | from selenium.webdriver.support.ui import Select | ||
33 | |||
34 | |||
35 | ########################################### | ||
36 | # # | ||
37 | # PART I: utils stuff # | ||
38 | # # | ||
39 | ########################################### | ||
40 | |||
41 | class Listattr(object): | ||
42 | """ | ||
43 | Set of list attribute. This is used to determine what the list content is. | ||
44 | Later on we may add more attributes here. | ||
45 | """ | ||
46 | NULL = "null" | ||
47 | NUMBERS = "numbers" | ||
48 | STRINGS = "strings" | ||
49 | PERCENT = "percentage" | ||
50 | SIZE = "size" | ||
51 | UNKNOWN = "unknown" | ||
52 | |||
53 | |||
54 | def get_log_root_dir(): | ||
55 | max_depth = 5 | ||
56 | parent_dir = '../' | ||
57 | for number in range(0, max_depth): | ||
58 | if os.path.isdir(sys.path[0] + os.sep + (os.pardir + os.sep)*number + 'log'): | ||
59 | log_root_dir = os.path.abspath(sys.path[0] + os.sep + (os.pardir + os.sep)*number + 'log') | ||
60 | break | ||
61 | |||
62 | if number == (max_depth - 1): | ||
63 | print 'No log dir found. Please check' | ||
64 | raise Exception | ||
65 | |||
66 | return log_root_dir | ||
67 | |||
68 | |||
69 | def mkdir_p(dir): | ||
70 | try: | ||
71 | os.makedirs(dir) | ||
72 | except OSError as exc: | ||
73 | if exc.errno == errno.EEXIST and os.path.isdir(dir): | ||
74 | pass | ||
75 | else: | ||
76 | raise | ||
77 | |||
78 | |||
79 | def get_list_attr(testlist): | ||
80 | """ | ||
81 | To determine the list content | ||
82 | """ | ||
83 | if not testlist: | ||
84 | return Listattr.NULL | ||
85 | listtest = testlist[:] | ||
86 | try: | ||
87 | listtest.remove('') | ||
88 | except ValueError: | ||
89 | pass | ||
90 | pattern_percent = re.compile(r"^([0-9])+(\.)?([0-9])*%$") | ||
91 | pattern_size = re.compile(r"^([0-9])+(\.)?([0-9])*( )*(K)*(M)*(G)*B$") | ||
92 | pattern_number = re.compile(r"^([0-9])+(\.)?([0-9])*$") | ||
93 | def get_patterned_number(pattern, tlist): | ||
94 | count = 0 | ||
95 | for item in tlist: | ||
96 | if re.search(pattern, item): | ||
97 | count += 1 | ||
98 | return count | ||
99 | if get_patterned_number(pattern_percent, listtest) == len(listtest): | ||
100 | return Listattr.PERCENT | ||
101 | elif get_patterned_number(pattern_size, listtest) == len(listtest): | ||
102 | return Listattr.SIZE | ||
103 | elif get_patterned_number(pattern_number, listtest) == len(listtest): | ||
104 | return Listattr.NUMBERS | ||
105 | else: | ||
106 | return Listattr.STRINGS | ||
107 | |||
108 | |||
109 | def is_list_sequenced(testlist): | ||
110 | """ | ||
111 | Function to tell if list is sequenced | ||
112 | Currently we may have list made up of: Strings ; numbers ; percentage ; time; size | ||
113 | Each has respective way to determine if it's sequenced. | ||
114 | """ | ||
115 | test_list = testlist[:] | ||
116 | try: | ||
117 | test_list.remove('') | ||
118 | except ValueError: | ||
119 | pass | ||
120 | |||
121 | if get_list_attr(testlist) == Listattr.NULL : | ||
122 | return True | ||
123 | |||
124 | elif get_list_attr(testlist) == Listattr.STRINGS : | ||
125 | return (sorted(test_list) == test_list) | ||
126 | |||
127 | elif get_list_attr(testlist) == Listattr.NUMBERS : | ||
128 | list_number = [] | ||
129 | for item in test_list: | ||
130 | list_number.append(eval(item)) | ||
131 | return (sorted(list_number) == list_number) | ||
132 | |||
133 | elif get_list_attr(testlist) == Listattr.PERCENT : | ||
134 | list_number = [] | ||
135 | for item in test_list: | ||
136 | list_number.append(eval(item.strip('%'))) | ||
137 | return (sorted(list_number) == list_number) | ||
138 | |||
139 | elif get_list_attr(testlist) == Listattr.SIZE : | ||
140 | list_number = [] | ||
141 | # currently SIZE is splitted by space | ||
142 | for item in test_list: | ||
143 | if item.split()[1].upper() == "KB": | ||
144 | list_number.append(1024 * eval(item.split()[0])) | ||
145 | elif item.split()[1].upper() == "MB": | ||
146 | list_number.append(1024 * 1024 * eval(item.split()[0])) | ||
147 | elif item.split()[1].upper() == "GB": | ||
148 | list_number.append(1024 * 1024 * 1024 * eval(item.split()[0])) | ||
149 | else: | ||
150 | list_number.append(eval(item.split()[0])) | ||
151 | return (sorted(list_number) == list_number) | ||
152 | |||
153 | else: | ||
154 | print 'Unrecognized list type, please check' | ||
155 | return False | ||
156 | |||
157 | |||
158 | def is_list_inverted(testlist): | ||
159 | """ | ||
160 | Function to tell if list is inverted | ||
161 | Currently we may have list made up of: Strings ; numbers ; percentage ; time; size | ||
162 | Each has respective way to determine if it's inverted. | ||
163 | """ | ||
164 | test_list = testlist[:] | ||
165 | try: | ||
166 | test_list.remove('') | ||
167 | except ValueError: | ||
168 | pass | ||
169 | |||
170 | if get_list_attr(testlist) == Listattr.NULL : | ||
171 | return True | ||
172 | |||
173 | elif get_list_attr(testlist) == Listattr.STRINGS : | ||
174 | return (sorted(test_list, reverse = True) == test_list) | ||
175 | |||
176 | elif get_list_attr(testlist) == Listattr.NUMBERS : | ||
177 | list_number = [] | ||
178 | for item in test_list: | ||
179 | list_number.append(eval(item)) | ||
180 | return (sorted(list_number, reverse = True) == list_number) | ||
181 | |||
182 | elif get_list_attr(testlist) == Listattr.PERCENT : | ||
183 | list_number = [] | ||
184 | for item in test_list: | ||
185 | list_number.append(eval(item.strip('%'))) | ||
186 | return (sorted(list_number, reverse = True) == list_number) | ||
187 | |||
188 | elif get_list_attr(testlist) == Listattr.SIZE : | ||
189 | list_number = [] | ||
190 | # currently SIZE is splitted by space. such as 0 B; 1 KB; 2 MB | ||
191 | for item in test_list: | ||
192 | if item.split()[1].upper() == "KB": | ||
193 | list_number.append(1024 * eval(item.split()[0])) | ||
194 | elif item.split()[1].upper() == "MB": | ||
195 | list_number.append(1024 * 1024 * eval(item.split()[0])) | ||
196 | elif item.split()[1].upper() == "GB": | ||
197 | list_number.append(1024 * 1024 * 1024 * eval(item.split()[0])) | ||
198 | else: | ||
199 | list_number.append(eval(item.split()[0])) | ||
200 | return (sorted(list_number, reverse = True) == list_number) | ||
201 | |||
202 | else: | ||
203 | print 'Unrecognized list type, please check' | ||
204 | return False | ||
205 | |||
206 | def replace_file_content(filename, item, option): | ||
207 | f = open(filename) | ||
208 | lines = f.readlines() | ||
209 | f.close() | ||
210 | output = open(filename, 'w') | ||
211 | for line in lines: | ||
212 | if line.startswith(item): | ||
213 | output.write(item + " = '" + option + "'\n") | ||
214 | else: | ||
215 | output.write(line) | ||
216 | output.close() | ||
217 | |||
218 | def extract_number_from_string(s): | ||
219 | """ | ||
220 | extract the numbers in a string. return type is 'list' | ||
221 | """ | ||
222 | return re.findall(r'([0-9]+)', s) | ||
223 | |||
224 | |||
225 | |||
226 | ########################################### | ||
227 | # # | ||
228 | # PART II: base class # | ||
229 | # # | ||
230 | ########################################### | ||
231 | |||
232 | class toaster_cases_base(unittest.TestCase): | ||
233 | |||
234 | def setUp(self): | ||
235 | self.screenshot_sequence = 1 | ||
236 | self.verificationErrors = [] | ||
237 | self.accept_next_alert = True | ||
238 | self.host_os = platform.system().lower() | ||
239 | self.parser = ConfigParser.SafeConfigParser() | ||
240 | configs = self.parser.read('toaster_test.cfg') | ||
241 | self.base_url = eval(self.parser.get('toaster_test_' + self.host_os, 'toaster_url')) | ||
242 | |||
243 | # create log dir . Currently , we put log files in log/tmp. After all | ||
244 | # test cases are done, move them to log/$datetime dir | ||
245 | self.log_tmp_dir = os.path.abspath(sys.path[0]) + os.sep + 'log' + os.sep + 'tmp' | ||
246 | try: | ||
247 | mkdir_p(self.log_tmp_dir) | ||
248 | except OSError : | ||
249 | logging.error("%(asctime)s Cannot create tmp dir under log, please check your privilege") | ||
250 | self.log = self.logger_create() | ||
251 | # driver setup | ||
252 | self.setup_browser() | ||
253 | |||
254 | def logger_create(self): | ||
255 | """ | ||
256 | we use root logger for every testcase. | ||
257 | The reason why we don't use TOASTERXXX_logger is to avoid setting respective level for | ||
258 | root logger and TOASTERXXX_logger | ||
259 | To Be Discussed | ||
260 | """ | ||
261 | log_level_dict = {'CRITICAL':logging.CRITICAL, 'ERROR':logging.ERROR, 'WARNING':logging.WARNING, \ | ||
262 | 'INFO':logging.INFO, 'DEBUG':logging.DEBUG, 'NOTSET':logging.NOTSET} | ||
263 | log = logging.getLogger() | ||
264 | # log = logging.getLogger('TOASTER_' + str(self.case_no)) | ||
265 | self.logging_level = eval(self.parser.get('toaster_test_' + self.host_os, 'logging_level')) | ||
266 | key = self.logging_level.upper() | ||
267 | log.setLevel(log_level_dict[key]) | ||
268 | fh = logging.FileHandler(filename=self.log_tmp_dir + os.sep + 'case_all' + '.log', mode='a') | ||
269 | ch = logging.StreamHandler(sys.stdout) | ||
270 | formatter = logging.Formatter('%(pathname)s - %(lineno)d - %(asctime)s \n \ | ||
271 | %(name)s - %(levelname)s - %(message)s') | ||
272 | fh.setFormatter(formatter) | ||
273 | ch.setFormatter(formatter) | ||
274 | log.addHandler(fh) | ||
275 | log.addHandler(ch) | ||
276 | return log | ||
277 | |||
278 | |||
279 | def setup_browser(self, *browser_path): | ||
280 | self.browser = eval(self.parser.get('toaster_test_' + self.host_os, 'test_browser')) | ||
281 | print self.browser | ||
282 | if self.browser == "firefox": | ||
283 | driver = webdriver.Firefox() | ||
284 | elif self.browser == "chrome": | ||
285 | driver = webdriver.Chrome() | ||
286 | elif self.browser == "ie": | ||
287 | driver = webdriver.Ie() | ||
288 | else: | ||
289 | driver = None | ||
290 | print "unrecognized browser type, please check" | ||
291 | self.driver = driver | ||
292 | self.driver.implicitly_wait(30) | ||
293 | return self.driver | ||
294 | |||
295 | |||
296 | def save_screenshot(self, **log_args): | ||
297 | """ | ||
298 | This function is used to save screen either by os interface or selenium interface. | ||
299 | How to use: | ||
300 | self.save_screenshot(screenshot_type = 'native'/'selenium', log_sub_dir = 'xxx', | ||
301 | append_name = 'stepx') | ||
302 | where native means screenshot func provided by OS, | ||
303 | selenium means screenshot func provided by selenium webdriver | ||
304 | """ | ||
305 | types = [log_args.get('screenshot_type')] | ||
306 | # when no screenshot_type is specified | ||
307 | if types == [None]: | ||
308 | types = ['native', 'selenium'] | ||
309 | # normally append_name is used to specify which step.. | ||
310 | add_name = log_args.get('append_name') | ||
311 | if not add_name: | ||
312 | add_name = '-' | ||
313 | # normally there's no need to specify sub_dir | ||
314 | sub_dir = log_args.get('log_sub_dir') | ||
315 | if not sub_dir: | ||
316 | # use casexxx as sub_dir name | ||
317 | sub_dir = 'case' + str(self.case_no) | ||
318 | for item in types: | ||
319 | log_dir = self.log_tmp_dir + os.sep + sub_dir | ||
320 | mkdir_p(log_dir) | ||
321 | log_path = log_dir + os.sep + self.browser + '-' +\ | ||
322 | item + '-' + add_name + '-' + str(self.screenshot_sequence) + '.png' | ||
323 | if item == 'native': | ||
324 | os.system("scrot " + log_path) | ||
325 | elif item == 'selenium': | ||
326 | self.driver.get_screenshot_as_file(log_path) | ||
327 | self.screenshot_sequence += 1 | ||
328 | |||
329 | def browser_delay(self): | ||
330 | """ | ||
331 | currently this is a workaround for some chrome test. | ||
332 | Sometimes we need a delay to accomplish some operation. | ||
333 | But for firefox, mostly we don't need this. | ||
334 | To be discussed | ||
335 | """ | ||
336 | if self.browser == "chrome": | ||
337 | time.sleep(1) | ||
338 | return | ||
339 | |||
340 | |||
341 | # these functions are not contained in WebDriver class.. | ||
342 | def find_element_by_text(self, string): | ||
343 | return self.driver.find_element_by_xpath("//*[text()='" + string + "']") | ||
344 | |||
345 | |||
346 | def find_elements_by_text(self, string): | ||
347 | return self.driver.find_elements_by_xpath("//*[text()='" + string + "']") | ||
348 | |||
349 | |||
350 | def find_element_by_text_in_table(self, table_id, text_string): | ||
351 | """ | ||
352 | This is used to search some certain 'text' in certain table | ||
353 | """ | ||
354 | try: | ||
355 | table_element = self.get_table_element(table_id) | ||
356 | element = table_element.find_element_by_xpath("//*[text()='" + text_string + "']") | ||
357 | except NoSuchElementException, e: | ||
358 | print 'no element found' | ||
359 | raise | ||
360 | return element | ||
361 | |||
362 | |||
363 | def find_element_by_link_text_in_table(self, table_id, link_text): | ||
364 | """ | ||
365 | Assume there're multiple suitable "find_element_by_link_text". | ||
366 | In this circumstance we need to specify "table". | ||
367 | """ | ||
368 | try: | ||
369 | table_element = self.get_table_element(table_id) | ||
370 | element = table_element.find_element_by_link_text(link_text) | ||
371 | except NoSuchElementException, e: | ||
372 | print 'no element found' | ||
373 | raise | ||
374 | return element | ||
375 | |||
376 | |||
377 | def find_elements_by_link_text_in_table(self, table_id, link_text): | ||
378 | """ | ||
379 | Search link-text in certain table. This helps to narrow down search area. | ||
380 | """ | ||
381 | try: | ||
382 | table_element = self.get_table_element(table_id) | ||
383 | element_list = table_element.find_elements_by_link_text(link_text) | ||
384 | except NoSuchElementException, e: | ||
385 | print 'no element found' | ||
386 | raise | ||
387 | return element_list | ||
388 | |||
389 | |||
390 | def find_element_by_partial_link_text_in_table(self, table_id, link_text): | ||
391 | """ | ||
392 | Search element by partial link text in certain table. | ||
393 | """ | ||
394 | try: | ||
395 | table_element = self.get_table_element(table_id) | ||
396 | element = table_element.find_element_by_partial_link_text(link_text) | ||
397 | return element | ||
398 | except NoSuchElementException, e: | ||
399 | print 'no element found' | ||
400 | raise | ||
401 | |||
402 | |||
403 | def find_elements_by_partial_link_text_in_table(self, table_id, link_text): | ||
404 | """ | ||
405 | Assume there're multiple suitable "find_partial_element_by_link_text". | ||
406 | """ | ||
407 | try: | ||
408 | table_element = self.get_table_element(table_id) | ||
409 | element_list = table_element.find_elements_by_partial_link_text(link_text) | ||
410 | return element_list | ||
411 | except NoSuchElementException, e: | ||
412 | print 'no element found' | ||
413 | raise | ||
414 | |||
415 | |||
416 | def find_element_by_xpath_in_table(self, table_id, xpath): | ||
417 | """ | ||
418 | This helps to narrow down search area. Especially useful when dealing with pop-up form. | ||
419 | """ | ||
420 | try: | ||
421 | table_element = self.get_table_element(table_id) | ||
422 | element = table_element.find_element_by_xpath(xpath) | ||
423 | except NoSuchElementException, e: | ||
424 | print 'no element found' | ||
425 | raise | ||
426 | return element | ||
427 | |||
428 | |||
429 | def find_elements_by_xpath_in_table(self, table_id, xpath): | ||
430 | """ | ||
431 | This helps to narrow down search area. Especially useful when dealing with pop-up form. | ||
432 | """ | ||
433 | try: | ||
434 | table_element = self.get_table_element(table_id) | ||
435 | element_list = table_element.find_elements_by_xpath(xpath) | ||
436 | except NoSuchElementException, e: | ||
437 | print 'no elements found' | ||
438 | raise | ||
439 | return element_list | ||
440 | |||
441 | |||
442 | def shortest_xpath(self, pname, pvalue): | ||
443 | return "//*[@" + pname + "='" + pvalue + "']" | ||
444 | |||
445 | |||
446 | #usually elements in the same column are with same class name. for instance: class="outcome" .TBD | ||
447 | def get_table_column_text(self, attr_name, attr_value): | ||
448 | c_xpath = self.shortest_xpath(attr_name, attr_value) | ||
449 | elements = self.driver.find_elements_by_xpath(c_xpath) | ||
450 | c_list = [] | ||
451 | for element in elements: | ||
452 | c_list.append(element.text) | ||
453 | return c_list | ||
454 | |||
455 | |||
456 | def get_table_column_text_by_column_number(self, table_id, column_number): | ||
457 | c_xpath = "//*[@id='" + table_id + "']//td[" + str(column_number) + "]" | ||
458 | elements = self.driver.find_elements_by_xpath(c_xpath) | ||
459 | c_list = [] | ||
460 | for element in elements: | ||
461 | c_list.append(element.text) | ||
462 | return c_list | ||
463 | |||
464 | |||
465 | def get_table_head_text(self, *table_id): | ||
466 | #now table_id is a tuple... | ||
467 | if table_id: | ||
468 | thead_xpath = "//*[@id='" + table_id[0] + "']//thead//th[text()]" | ||
469 | elements = self.driver.find_elements_by_xpath(thead_xpath) | ||
470 | c_list = [] | ||
471 | for element in elements: | ||
472 | if element.text: | ||
473 | c_list.append(element.text) | ||
474 | return c_list | ||
475 | #default table on page | ||
476 | else: | ||
477 | return self.driver.find_element_by_xpath("//*/table/thead").text | ||
478 | |||
479 | |||
480 | |||
481 | def get_table_element(self, table_id, *coordinate): | ||
482 | if len(coordinate) == 0: | ||
483 | #return whole-table element | ||
484 | element_xpath = "//*[@id='" + table_id + "']" | ||
485 | try: | ||
486 | element = self.driver.find_element_by_xpath(element_xpath) | ||
487 | except NoSuchElementException, e: | ||
488 | raise | ||
489 | return element | ||
490 | row = coordinate[0] | ||
491 | |||
492 | if len(coordinate) == 1: | ||
493 | #return whole-row element | ||
494 | element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]" | ||
495 | try: | ||
496 | element = self.driver.find_element_by_xpath(element_xpath) | ||
497 | except NoSuchElementException, e: | ||
498 | return False | ||
499 | return element | ||
500 | #now we are looking for an element with specified X and Y | ||
501 | column = coordinate[1] | ||
502 | |||
503 | element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]/td[" + str(column) + "]" | ||
504 | try: | ||
505 | element = self.driver.find_element_by_xpath(element_xpath) | ||
506 | except NoSuchElementException, e: | ||
507 | return False | ||
508 | return element | ||
509 | |||
510 | |||
511 | def get_table_data(self, table_id, row_count, column_count): | ||
512 | row = 1 | ||
513 | Lists = [] | ||
514 | while row <= row_count: | ||
515 | column = 1 | ||
516 | row_content=[] | ||
517 | while column <= column_count: | ||
518 | s= "//*[@id='" + table_id + "']/tbody/tr[" + str(row) +"]/td[" + str(column) + "]" | ||
519 | v = self.driver.find_element_by_xpath(s).text | ||
520 | row_content.append(v) | ||
521 | column = column + 1 | ||
522 | print("row_content=",row_content) | ||
523 | Lists.extend(row_content) | ||
524 | print Lists[row-1][0] | ||
525 | row = row + 1 | ||
526 | return Lists | ||
527 | |||
528 | # The is_xxx_present functions only returns True/False | ||
529 | # All the log work is done in test procedure, so we can easily trace back | ||
530 | # using logging | ||
531 | def is_text_present (self, patterns): | ||
532 | for pattern in patterns: | ||
533 | if str(pattern) not in self.driver.page_source: | ||
534 | return False | ||
535 | return True | ||
536 | |||
537 | |||
538 | def is_element_present(self, how, what): | ||
539 | try: | ||
540 | self.driver.find_element(how, what) | ||
541 | except NoSuchElementException, e: | ||
542 | return False | ||
543 | return True | ||
544 | |||
545 | |||
546 | def is_alert_present(self): | ||
547 | try: self.driver.switch_to_alert() | ||
548 | except NoAlertPresentException, e: return False | ||
549 | return True | ||
550 | |||
551 | |||
552 | def close_alert_and_get_its_text(self): | ||
553 | try: | ||
554 | alert = self.driver.switch_to_alert() | ||
555 | alert_text = alert.text | ||
556 | if self.accept_next_alert: | ||
557 | alert.accept() | ||
558 | else: | ||
559 | alert.dismiss() | ||
560 | return alert_text | ||
561 | finally: self.accept_next_alert = True | ||
562 | |||
563 | |||
564 | def get_case_number(self): | ||
565 | """ | ||
566 | what case are we running now | ||
567 | """ | ||
568 | funcname = sys._getframe(1).f_code.co_name | ||
569 | caseno_str = funcname.strip('test_') | ||
570 | try: | ||
571 | caseno = int(caseno_str) | ||
572 | except ValueError: | ||
573 | print "get case number error! please check if func name is test_xxx" | ||
574 | return False | ||
575 | return caseno | ||
576 | |||
577 | |||
578 | def tearDown(self): | ||
579 | self.log.info(' END: CASE %s log \n\n' % str(self.case_no)) | ||
580 | self.driver.quit() | ||
581 | self.assertEqual([], self.verificationErrors) | ||
582 | |||
583 | |||
584 | ################################################################### | ||
585 | # # | ||
586 | # PART III: test cases # | ||
587 | # please refer to # | ||
588 | # https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=xxx # | ||
589 | # # | ||
590 | ################################################################### | ||
591 | |||
592 | # Note: to comply with the unittest framework, we call these test_xxx functions | ||
593 | # from run_toastercases.py to avoid calling setUp() and tearDown() multiple times | ||
594 | |||
595 | |||
596 | class toaster_cases(toaster_cases_base): | ||
597 | ############## | ||
598 | # CASE 901 # | ||
599 | ############## | ||
600 | def test_901(self): | ||
601 | # the reason why get_case_number is not in setUp function is that | ||
602 | # otherwise it returns "setUp" instead of "test_xxx" | ||
603 | self.case_no = self.get_case_number() | ||
604 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
605 | self.driver.maximize_window() | ||
606 | self.driver.get(self.base_url) | ||
607 | # open all columns | ||
608 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
609 | # adding explicitly wait for chromedriver..-_- | ||
610 | self.browser_delay() | ||
611 | self.driver.find_element_by_id("log").click() | ||
612 | self.browser_delay() | ||
613 | self.driver.find_element_by_id("started_on").click() | ||
614 | self.browser_delay() | ||
615 | self.driver.find_element_by_id("time").click() | ||
616 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
617 | # dict: {lint text name : actual class name} | ||
618 | table_head_dict = {'Outcome':'outcome', 'Target':'target', 'Machine':'machine', 'Started on':'started_on', 'Completed on':'completed_on', \ | ||
619 | 'Errors':'errors_no', 'Warnings':'warnings_no', 'Time':'time', 'Log':'log'} | ||
620 | for key in table_head_dict: | ||
621 | try: | ||
622 | self.driver.find_element_by_link_text(key).click() | ||
623 | except Exception, e: | ||
624 | self.log.error("%s cannot be found on page" % key) | ||
625 | raise | ||
626 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
627 | # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here | ||
628 | # the point is, after another click, it should be another order | ||
629 | if is_list_inverted(column_list): | ||
630 | self.driver.find_element_by_link_text(key).click() | ||
631 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
632 | self.failUnless(is_list_sequenced(column_list)) | ||
633 | else: | ||
634 | self.failUnless(is_list_sequenced(column_list)) | ||
635 | self.driver.find_element_by_link_text(key).click() | ||
636 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
637 | self.failUnless(is_list_inverted(column_list)) | ||
638 | self.log.info("case passed") | ||
639 | |||
640 | |||
641 | ############## | ||
642 | # CASE 902 # | ||
643 | ############## | ||
644 | def test_902(self): | ||
645 | self.case_no = self.get_case_number() | ||
646 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
647 | self.driver.maximize_window() | ||
648 | self.driver.get(self.base_url) | ||
649 | # Could add more test patterns here in the future. Also, could search some items other than target column in future.. | ||
650 | patterns = ["minimal", "sato"] | ||
651 | for pattern in patterns: | ||
652 | ori_target_column_texts = self.get_table_column_text("class", "target") | ||
653 | print ori_target_column_texts | ||
654 | self.driver.find_element_by_id("search").clear() | ||
655 | self.driver.find_element_by_id("search").send_keys(pattern) | ||
656 | self.driver.find_element_by_css_selector("button.btn").click() | ||
657 | new_target_column_texts = self.get_table_column_text("class", "target") | ||
658 | # if nothing found, we still count it as "pass" | ||
659 | if new_target_column_texts: | ||
660 | for text in new_target_column_texts: | ||
661 | self.failUnless(text.find(pattern)) | ||
662 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
663 | target_column_texts = self.get_table_column_text("class", "target") | ||
664 | self.failUnless(ori_target_column_texts == target_column_texts) | ||
665 | |||
666 | |||
667 | ############## | ||
668 | # CASE 903 # | ||
669 | ############## | ||
670 | def test_903(self): | ||
671 | self.case_no = self.get_case_number() | ||
672 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
673 | self.driver.maximize_window() | ||
674 | self.driver.get(self.base_url) | ||
675 | # when opening a new page, "started_on" is not displayed by default | ||
676 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
677 | # currently all the delay are for chrome driver -_- | ||
678 | self.browser_delay() | ||
679 | self.driver.find_element_by_id("started_on").click() | ||
680 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
681 | # step 4 | ||
682 | items = ["Outcome", "Completed on", "Started on", "Failed tasks", "Errors", "Warnings"] | ||
683 | for item in items: | ||
684 | try: | ||
685 | temp_element = self.find_element_by_text_in_table('otable', item) | ||
686 | # this is how we find "filter icon" in the same level as temp_element(where "a" means clickable, "i" means icon) | ||
687 | self.failUnless(temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']")) | ||
688 | except Exception,e: | ||
689 | self.log.error(" %s cannot be found! %s" % (item, e)) | ||
690 | self.failIf(True) | ||
691 | raise | ||
692 | # step 5-6 | ||
693 | temp_element = self.find_element_by_link_text_in_table('otable', 'Outcome') | ||
694 | temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click() | ||
695 | self.browser_delay() | ||
696 | # the 2nd option, whatever it is | ||
697 | self.driver.find_element_by_xpath("(//input[@name='filter'])[2]").click() | ||
698 | # click "Apply" button | ||
699 | self.driver.find_element_by_xpath("//*[@id='filter_outcome']//*[text()='Apply']").click() | ||
700 | # save screen here | ||
701 | time.sleep(1) | ||
702 | self.save_screenshot(screenshot_type='selenium', append_name='step5') | ||
703 | temp_element = self.find_element_by_link_text_in_table('otable', 'Completed on') | ||
704 | temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click() | ||
705 | self.browser_delay() | ||
706 | self.driver.find_element_by_xpath("//*[@id='filter_completed_on']//*[text()='Apply']").click() | ||
707 | # save screen here to compare to previous one | ||
708 | # please note that for chrome driver, need a little break before saving | ||
709 | # screen here -_- | ||
710 | self.browser_delay() | ||
711 | self.save_screenshot(screenshot_type='selenium', append_name='step6') | ||
712 | self.driver.find_element_by_id("search").clear() | ||
713 | self.driver.find_element_by_id("search").send_keys("core-image") | ||
714 | self.driver.find_element_by_css_selector("button.btn").click() | ||
715 | |||
716 | |||
717 | ############## | ||
718 | # CASE 904 # | ||
719 | ############## | ||
720 | def test_904(self): | ||
721 | self.case_no = self.get_case_number() | ||
722 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
723 | self.driver.maximize_window() | ||
724 | self.driver.get(self.base_url) | ||
725 | self.driver.find_element_by_partial_link_text("core-image").click() | ||
726 | self.driver.find_element_by_link_text("Tasks").click() | ||
727 | # self.driver.find_element_by_link_text("All builds").click() | ||
728 | # self.driver.back() | ||
729 | self.table_name = 'otable' | ||
730 | # This is how we find the "default" rows-number! | ||
731 | rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text) | ||
732 | print rows_displayed | ||
733 | self.failUnless(self.get_table_element(self.table_name, rows_displayed)) | ||
734 | self.failIf(self.get_table_element(self.table_name, rows_displayed + 1)) | ||
735 | # Search text box background text is "Search tasks" | ||
736 | self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search tasks']")) | ||
737 | |||
738 | self.driver.find_element_by_id("search").clear() | ||
739 | self.driver.find_element_by_id("search").send_keys("busybox") | ||
740 | self.driver.find_element_by_css_selector("button.btn").click() | ||
741 | self.browser_delay() | ||
742 | self.save_screenshot(screenshot_type='selenium', append_name='step5') | ||
743 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
744 | # Save screen here | ||
745 | self.save_screenshot(screenshot_type='selenium', append_name='step5_2') | ||
746 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
747 | self.driver.find_element_by_id("cpu_used").click() | ||
748 | self.driver.find_element_by_id("disk_io").click() | ||
749 | self.driver.find_element_by_id("task_log").click() | ||
750 | self.driver.find_element_by_id("recipe_version").click() | ||
751 | self.driver.find_element_by_id("time_taken").click() | ||
752 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
753 | # The operation is the same as case901 | ||
754 | # dict: {lint text name : actual class name} | ||
755 | table_head_dict = {'Order':'order', 'Recipe':'recipe_name', 'Task':'task_name', 'Executed':'executed', \ | ||
756 | 'Outcome':'outcome', 'Cache attempt':'cache_attempt', 'Time (secs)':'time_taken', 'CPU usage':'cpu_used', \ | ||
757 | 'Disk I/O (ms)':'disk_io', 'Log':'task_log'} | ||
758 | for key in table_head_dict: | ||
759 | # This is tricky here: we are doing so because there may be more than 1 | ||
760 | # same-name link_text in one page. So we only find element inside the table | ||
761 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
762 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
763 | # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here | ||
764 | # the point is, after another click, it should be another order | ||
765 | # the fist case is special:this means every item in column_list is the same, so | ||
766 | # after one click, either sequenced or inverted will be fine | ||
767 | if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \ | ||
768 | or (not column_list) : | ||
769 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
770 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
771 | self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list)) | ||
772 | elif is_list_inverted(column_list): | ||
773 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
774 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
775 | self.failUnless(is_list_sequenced(column_list)) | ||
776 | else: | ||
777 | self.failUnless(is_list_sequenced(column_list)) | ||
778 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
779 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
780 | self.failUnless(is_list_inverted(column_list)) | ||
781 | # step 8-10 | ||
782 | # filter dict: {link text name : filter table name in xpath} | ||
783 | filter_dict = {'Executed':'filter_executed', 'Outcome':'filter_outcome', 'Cache attempt':'filter_cache_attempt'} | ||
784 | for key in filter_dict: | ||
785 | temp_element = self.find_element_by_link_text_in_table(self.table_name, key) | ||
786 | # find the filter icon besides it. | ||
787 | # And here we must have break (1 sec) to get the popup stuff | ||
788 | temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click() | ||
789 | self.browser_delay() | ||
790 | avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]") | ||
791 | for number in range(0, len(avail_options)): | ||
792 | avail_options[number].click() | ||
793 | self.browser_delay() | ||
794 | # click "Apply" | ||
795 | self.driver.find_element_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@type='submit']").click() | ||
796 | # insert screen capture here | ||
797 | self.browser_delay() | ||
798 | self.save_screenshot(screenshot_type='selenium', append_name='step8') | ||
799 | # after the last option was clicked, we don't need operation below anymore | ||
800 | if number < len(avail_options)-1: | ||
801 | temp_element = self.find_element_by_link_text_in_table(self.table_name, key) | ||
802 | temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click() | ||
803 | avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]") | ||
804 | self.browser_delay() | ||
805 | # step 11 | ||
806 | for item in ['order', 'task_name', 'executed', 'outcome', 'recipe_name', 'recipe_version']: | ||
807 | try: | ||
808 | self.find_element_by_xpath_in_table(self.table_name, "./tbody/tr[1]/*[@class='" + item + "']/a").click() | ||
809 | except NoSuchElementException, e: | ||
810 | # let it go... | ||
811 | print 'no item in the colum' + item | ||
812 | # insert screen shot here | ||
813 | self.save_screenshot(screenshot_type='selenium', append_name='step11') | ||
814 | self.driver.back() | ||
815 | # step 12-14 | ||
816 | # about test_dict: please refer to testcase 904 requirement step 12-14 | ||
817 | test_dict = { | ||
818 | 'Time':{ | ||
819 | 'class':'time_taken', | ||
820 | 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Time (secs)'], | ||
821 | 'check_column_list':['cpu_used', 'cache_attempt', 'disk_io', 'task_log', 'order', 'recipe_version'] | ||
822 | }, | ||
823 | 'CPU usage':{ | ||
824 | 'class':'cpu_used', | ||
825 | 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'CPU usage'], | ||
826 | 'check_column_list':['cache_attempt', 'disk_io', 'task_log', 'order', 'recipe_version', 'time_taken'] | ||
827 | }, | ||
828 | 'Disk I/O':{ | ||
829 | 'class':'disk_io', | ||
830 | 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Disk I/O (ms)'], | ||
831 | 'check_column_list':['cpu_used', 'cache_attempt', 'task_log', 'order', 'recipe_version', 'time_taken'] | ||
832 | } | ||
833 | } | ||
834 | for key in test_dict: | ||
835 | self.find_element_by_partial_link_text_in_table('nav', 'core-image').click() | ||
836 | self.find_element_by_link_text_in_table('nav', key).click() | ||
837 | head_list = self.get_table_head_text('otable') | ||
838 | for item in test_dict[key]['check_head_list']: | ||
839 | self.failUnless(item in head_list) | ||
840 | column_list = self.get_table_column_text('class', test_dict[key]['class']) | ||
841 | self.failUnless(is_list_inverted(column_list)) | ||
842 | |||
843 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
844 | for item2 in test_dict[key]['check_column_list']: | ||
845 | self.driver.find_element_by_id(item2).click() | ||
846 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
847 | # TBD: save screen here | ||
848 | |||
849 | |||
850 | ############## | ||
851 | # CASE 906 # | ||
852 | ############## | ||
853 | def test_906(self): | ||
854 | self.case_no = self.get_case_number() | ||
855 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
856 | self.driver.maximize_window() | ||
857 | self.driver.get(self.base_url) | ||
858 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
859 | self.find_element_by_link_text_in_table('nav', 'Packages').click() | ||
860 | # find "bash" in first column (Packages) | ||
861 | self.driver.find_element_by_xpath("//*[@id='otable']//td[1]//*[text()='bash']").click() | ||
862 | # save sceen here to observe... | ||
863 | # step 6 | ||
864 | self.driver.find_element_by_partial_link_text("Generated files").click() | ||
865 | head_list = self.get_table_head_text('otable') | ||
866 | for item in ['File', 'Size']: | ||
867 | self.failUnless(item in head_list) | ||
868 | c_list = self.get_table_column_text('class', 'path') | ||
869 | self.failUnless(is_list_sequenced(c_list)) | ||
870 | # step 7 | ||
871 | self.driver.find_element_by_partial_link_text("Runtime dependencies").click() | ||
872 | # save sceen here to observe... | ||
873 | # note that here table name is not 'otable' | ||
874 | head_list = self.get_table_head_text('dependencies') | ||
875 | for item in ['Package', 'Version', 'Size']: | ||
876 | self.failUnless(item in head_list) | ||
877 | c_list = self.get_table_column_text_by_column_number('dependencies', 1) | ||
878 | self.failUnless(is_list_sequenced(c_list)) | ||
879 | texts = ['Size', 'License', 'Recipe', 'Recipe version', 'Layer', \ | ||
880 | 'Layer branch', 'Layer commit', 'Layer directory'] | ||
881 | self.failUnless(self.is_text_present(texts)) | ||
882 | |||
883 | |||
884 | ############## | ||
885 | # CASE 910 # | ||
886 | ############## | ||
887 | def test_910(self): | ||
888 | self.case_no = self.get_case_number() | ||
889 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
890 | image_type="core-image-minimal" | ||
891 | test_package1="busybox" | ||
892 | test_package2="lib" | ||
893 | self.driver.maximize_window() | ||
894 | self.driver.get(self.base_url) | ||
895 | self.driver.find_element_by_link_text(image_type).click() | ||
896 | self.driver.find_element_by_link_text("Recipes").click() | ||
897 | self.save_screenshot(screenshot_type='selenium', append_name='step3') | ||
898 | |||
899 | self.table_name = 'otable' | ||
900 | # This is how we find the "default" rows-number! | ||
901 | rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text) | ||
902 | print rows_displayed | ||
903 | self.failUnless(self.get_table_element(self.table_name, rows_displayed)) | ||
904 | self.failIf(self.get_table_element(self.table_name, rows_displayed + 1)) | ||
905 | |||
906 | # Check the default table is sorted by Recipe | ||
907 | tasks_column_count = len(self.driver.find_elements_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr/td[1]")) | ||
908 | print tasks_column_count | ||
909 | default_column_list = self.get_table_column_text_by_column_number(self.table_name, 1) | ||
910 | #print default_column_list | ||
911 | |||
912 | self.failUnless(is_list_sequenced(default_column_list)) | ||
913 | |||
914 | # Search text box background text is "Search recipes" | ||
915 | self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']")) | ||
916 | |||
917 | self.driver.find_element_by_id("search").clear() | ||
918 | self.driver.find_element_by_id("search").send_keys(test_package1) | ||
919 | self.driver.find_element_by_css_selector("button.btn").click() | ||
920 | # Save screen here | ||
921 | self.save_screenshot(screenshot_type='selenium', append_name='step4') | ||
922 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
923 | self.save_screenshot(screenshot_type='selenium', append_name='step4_2') | ||
924 | |||
925 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
926 | self.driver.find_element_by_id("depends_on").click() | ||
927 | self.driver.find_element_by_id("layer_version__branch").click() | ||
928 | self.driver.find_element_by_id("layer_version__layer__commit").click() | ||
929 | self.driver.find_element_by_id("layer_version__layer__local_path").click() | ||
930 | self.driver.find_element_by_id("depends_by").click() | ||
931 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
932 | |||
933 | self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click() | ||
934 | # Check the inverted table by Recipe | ||
935 | # Recipe doesn't have class name | ||
936 | inverted_tasks_column_count = len(self.driver.find_elements_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr/td[1]")) | ||
937 | print inverted_tasks_column_count | ||
938 | inverted_column_list = self.get_table_column_text_by_column_number(self.table_name, 1) | ||
939 | #print inverted_column_list | ||
940 | |||
941 | self.driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr[1]/td[1]/a").click() | ||
942 | self.driver.back() | ||
943 | self.failUnless(is_list_inverted(inverted_column_list)) | ||
944 | self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click() | ||
945 | |||
946 | table_head_dict = {'Recipe file':'recipe_file', 'Section':'recipe_section', \ | ||
947 | 'License':'recipe_license', 'Layer':'layer_version__layer__name', \ | ||
948 | 'Layer branch':'layer_version__branch', 'Layer directory':'layer_version__layer__local_path'} | ||
949 | for key in table_head_dict: | ||
950 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
951 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
952 | if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \ | ||
953 | or (not column_list) : | ||
954 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
955 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
956 | self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list)) | ||
957 | self.driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr[1]/td[1]/a").click() | ||
958 | self.driver.back() | ||
959 | self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list)) | ||
960 | # Search text box background text is "Search recipes" | ||
961 | self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']")) | ||
962 | self.driver.find_element_by_id("search").clear() | ||
963 | self.driver.find_element_by_id("search").send_keys(test_package2) | ||
964 | self.driver.find_element_by_css_selector("button.btn").click() | ||
965 | column_search_list = self.get_table_column_text("class", table_head_dict[key]) | ||
966 | self.failUnless(is_list_sequenced(column_search_list) or is_list_inverted(column_search_list)) | ||
967 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
968 | elif is_list_inverted(column_list): | ||
969 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
970 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
971 | self.failUnless(is_list_sequenced(column_list)) | ||
972 | self.driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr[1]/td[1]/a").click() | ||
973 | self.driver.back() | ||
974 | self.failUnless(is_list_sequenced(column_list)) | ||
975 | # Search text box background text is "Search recipes" | ||
976 | self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']")) | ||
977 | self.driver.find_element_by_id("search").clear() | ||
978 | self.driver.find_element_by_id("search").send_keys(test_package2) | ||
979 | self.driver.find_element_by_css_selector("button.btn").click() | ||
980 | column_search_list = self.get_table_column_text("class", table_head_dict[key]) | ||
981 | self.failUnless(is_list_sequenced(column_search_list)) | ||
982 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
983 | else: | ||
984 | self.failUnless(is_list_sequenced(column_list)) | ||
985 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
986 | column_list = self.get_table_column_text("class", table_head_dict[key]) | ||
987 | self.failUnless(is_list_inverted(column_list)) | ||
988 | self.driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr[1]/td[1]/a").click() | ||
989 | self.driver.back() | ||
990 | self.failUnless(is_list_inverted(column_list)) | ||
991 | # Search text box background text is "Search recipes" | ||
992 | self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']")) | ||
993 | self.driver.find_element_by_id("search").clear() | ||
994 | self.driver.find_element_by_id("search").send_keys(test_package2) | ||
995 | self.driver.find_element_by_css_selector("button.btn").click() | ||
996 | column_search_list = self.get_table_column_text("class", table_head_dict[key]) | ||
997 | #print column_search_list | ||
998 | self.failUnless(is_list_inverted(column_search_list)) | ||
999 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
1000 | |||
1001 | # Bug 5919 | ||
1002 | for key in table_head_dict: | ||
1003 | print key | ||
1004 | self.find_element_by_link_text_in_table(self.table_name, key).click() | ||
1005 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1006 | self.driver.find_element_by_id(table_head_dict[key]).click() | ||
1007 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1008 | self.browser_delay() | ||
1009 | # After hide the column, the default table should be sorted by Recipe | ||
1010 | tasks_column_count = len(self.driver.find_elements_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr/td[1]")) | ||
1011 | #print tasks_column_count | ||
1012 | default_column_list = self.get_table_column_text_by_column_number(self.table_name, 1) | ||
1013 | #print default_column_list | ||
1014 | self.failUnless(is_list_sequenced(default_column_list)) | ||
1015 | |||
1016 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1017 | self.driver.find_element_by_id("recipe_file").click() | ||
1018 | self.driver.find_element_by_id("recipe_section").click() | ||
1019 | self.driver.find_element_by_id("recipe_license").click() | ||
1020 | self.driver.find_element_by_id("layer_version__layer__name").click() | ||
1021 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1022 | |||
1023 | |||
1024 | ############## | ||
1025 | # CASE 911 # | ||
1026 | ############## | ||
1027 | def test_911(self): | ||
1028 | self.case_no = self.get_case_number() | ||
1029 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1030 | self.driver.maximize_window() | ||
1031 | self.driver.get(self.base_url) | ||
1032 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1033 | self.find_element_by_link_text_in_table('nav', 'Recipes').click() | ||
1034 | # step 3-5 | ||
1035 | self.driver.find_element_by_id("search").clear() | ||
1036 | self.driver.find_element_by_id("search").send_keys("lib") | ||
1037 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1038 | # save screen here for observation | ||
1039 | self.save_screenshot(screenshot_type='selenium', append_name='step5') | ||
1040 | # step 6 | ||
1041 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
1042 | self.driver.find_element_by_id("search").clear() | ||
1043 | # we deliberately want "no result" here | ||
1044 | self.driver.find_element_by_id("search").send_keys("what the hell") | ||
1045 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1046 | self.find_element_by_text("Show all recipes").click() | ||
1047 | self.driver.quit() | ||
1048 | |||
1049 | |||
1050 | ############## | ||
1051 | # CASE 912 # | ||
1052 | ############## | ||
1053 | def test_912(self): | ||
1054 | self.case_no = self.get_case_number() | ||
1055 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1056 | self.driver = self.setup_browser(self) | ||
1057 | self.driver.maximize_window() | ||
1058 | self.driver.get(self.base_url) | ||
1059 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1060 | self.find_element_by_link_text_in_table('nav', 'Recipes').click() | ||
1061 | # step 3 | ||
1062 | head_list = self.get_table_head_text('otable') | ||
1063 | for item in ['Recipe', 'Recipe version', 'Recipe file', 'Section', 'License', 'Layer']: | ||
1064 | self.failUnless(item in head_list) | ||
1065 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1066 | self.driver.find_element_by_id("depends_on").click() | ||
1067 | self.driver.find_element_by_id("layer_version__branch").click() | ||
1068 | self.driver.find_element_by_id("layer_version__layer__commit").click() | ||
1069 | self.driver.find_element_by_id("layer_version__layer__local_path").click() | ||
1070 | self.driver.find_element_by_id("depends_by").click() | ||
1071 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1072 | # check if columns selected above is shown | ||
1073 | check_list = ['Dependencies', 'Layer branch', 'Layer commit', 'Layer directory', 'Reverse dependencies'] | ||
1074 | head_list = self.get_table_head_text('otable') | ||
1075 | time.sleep(2) | ||
1076 | print head_list | ||
1077 | for item in check_list: | ||
1078 | self.failUnless(item in head_list) | ||
1079 | # un-check 'em all | ||
1080 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1081 | self.driver.find_element_by_id("depends_on").click() | ||
1082 | self.driver.find_element_by_id("layer_version__branch").click() | ||
1083 | self.driver.find_element_by_id("layer_version__layer__commit").click() | ||
1084 | self.driver.find_element_by_id("layer_version__layer__local_path").click() | ||
1085 | self.driver.find_element_by_id("depends_by").click() | ||
1086 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1087 | # don't exist any more | ||
1088 | head_list = self.get_table_head_text('otable') | ||
1089 | for item in check_list: | ||
1090 | self.failIf(item in head_list) | ||
1091 | |||
1092 | |||
1093 | ############## | ||
1094 | # CASE 913 # | ||
1095 | ############## | ||
1096 | def test_913(self): | ||
1097 | self.case_no = self.get_case_number() | ||
1098 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1099 | self.driver.maximize_window() | ||
1100 | self.driver.get(self.base_url) | ||
1101 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1102 | self.find_element_by_link_text_in_table('nav', 'Recipes').click() | ||
1103 | # step 3 | ||
1104 | head_list = self.get_table_head_text('otable') | ||
1105 | for item in ['Recipe', 'Recipe version', 'Recipe file', 'Section', 'License', 'Layer']: | ||
1106 | self.failUnless(item in head_list) | ||
1107 | # step 4 | ||
1108 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1109 | # save screen | ||
1110 | self.browser_delay() | ||
1111 | self.save_screenshot(screenshot_type='selenium', append_name='step4') | ||
1112 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1113 | |||
1114 | |||
1115 | ############## | ||
1116 | # CASE 914 # | ||
1117 | ############## | ||
1118 | def test_914(self): | ||
1119 | self.case_no = self.get_case_number() | ||
1120 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1121 | image_type="core-image-minimal" | ||
1122 | test_package1="busybox" | ||
1123 | test_package2="gdbm" | ||
1124 | test_package3="gettext-native" | ||
1125 | driver = self.driver | ||
1126 | driver.maximize_window() | ||
1127 | driver.get(self.base_url) | ||
1128 | driver.find_element_by_link_text(image_type).click() | ||
1129 | driver.find_element_by_link_text("Recipes").click() | ||
1130 | driver.find_element_by_link_text(test_package1).click() | ||
1131 | |||
1132 | self.table_name = 'information' | ||
1133 | |||
1134 | tasks_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr/td[1]")) | ||
1135 | tasks_column_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr[1]/td")) | ||
1136 | print tasks_row_count | ||
1137 | print tasks_column_count | ||
1138 | |||
1139 | Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2) | ||
1140 | print ("Tasks_column=", Tasks_column) | ||
1141 | |||
1142 | key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_package", "do_build"] | ||
1143 | i = 0 | ||
1144 | while i < len(key_tasks): | ||
1145 | if key_tasks[i] not in Tasks_column: | ||
1146 | print ("Error! Missing key task: %s" % key_tasks[i]) | ||
1147 | else: | ||
1148 | print ("%s is in tasks" % key_tasks[i]) | ||
1149 | i = i + 1 | ||
1150 | |||
1151 | if Tasks_column.index(key_tasks[0]) != 0: | ||
1152 | print ("Error! %s is not in the right position" % key_tasks[0]) | ||
1153 | else: | ||
1154 | print ("%s is in right position" % key_tasks[0]) | ||
1155 | |||
1156 | if Tasks_column[-1] != key_tasks[-1]: | ||
1157 | print ("Error! %s is not in the right position" % key_tasks[-1]) | ||
1158 | else: | ||
1159 | print ("%s is in right position" % key_tasks[-1]) | ||
1160 | |||
1161 | driver.find_element_by_partial_link_text("Packages (").click() | ||
1162 | packages_name = driver.find_element_by_partial_link_text("Packages (").text | ||
1163 | print packages_name | ||
1164 | packages_num = string.atoi(filter(str.isdigit, repr(packages_name))) | ||
1165 | print packages_num | ||
1166 | |||
1167 | packages_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[2]/table/tbody/tr/td[1]")) | ||
1168 | print packages_row_count | ||
1169 | |||
1170 | if packages_num != packages_row_count: | ||
1171 | print ("Error! The packages number is not correct") | ||
1172 | else: | ||
1173 | print ("The pakcages number is correct") | ||
1174 | |||
1175 | driver.find_element_by_partial_link_text("Build dependencies (").click() | ||
1176 | depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text | ||
1177 | print depends_name | ||
1178 | depends_num = string.atoi(filter(str.isdigit, repr(depends_name))) | ||
1179 | print depends_num | ||
1180 | |||
1181 | if depends_num == 0: | ||
1182 | depends_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text) | ||
1183 | print depends_message | ||
1184 | if depends_message.find("has no build dependencies.") < 0: | ||
1185 | print ("Error! The message isn't expected.") | ||
1186 | else: | ||
1187 | print ("The message is expected") | ||
1188 | else: | ||
1189 | depends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[3]/table/tbody/tr/td[1]")) | ||
1190 | print depends_row_count | ||
1191 | if depends_num != depends_row_count: | ||
1192 | print ("Error! The dependent packages number is not correct") | ||
1193 | else: | ||
1194 | print ("The dependent packages number is correct") | ||
1195 | |||
1196 | driver.find_element_by_partial_link_text("Reverse build dependencies (").click() | ||
1197 | rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text | ||
1198 | print rdepends_name | ||
1199 | rdepends_num = string.atoi(filter(str.isdigit, repr(rdepends_name))) | ||
1200 | print rdepends_num | ||
1201 | |||
1202 | if rdepends_num == 0: | ||
1203 | rdepends_message = repr(driver.find_element_by_css_selector("#brought-in-by > div.alert.alert-info").text) | ||
1204 | print rdepends_message | ||
1205 | if rdepends_message.find("has no reverse build dependencies.") < 0: | ||
1206 | print ("Error! The message isn't expected.") | ||
1207 | else: | ||
1208 | print ("The message is expected") | ||
1209 | else: | ||
1210 | print ("The reverse dependent packages number is correct") | ||
1211 | |||
1212 | driver.find_element_by_link_text("Recipes").click() | ||
1213 | driver.find_element_by_link_text(test_package2).click() | ||
1214 | driver.find_element_by_partial_link_text("Packages (").click() | ||
1215 | driver.find_element_by_partial_link_text("Build dependencies (").click() | ||
1216 | driver.find_element_by_partial_link_text("Reverse build dependencies (").click() | ||
1217 | |||
1218 | |||
1219 | driver.find_element_by_link_text("Recipes").click() | ||
1220 | driver.find_element_by_link_text(test_package3).click() | ||
1221 | |||
1222 | native_tasks_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr/td[1]")) | ||
1223 | native_tasks_column_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr[1]/td")) | ||
1224 | print native_tasks_row_count | ||
1225 | print native_tasks_column_count | ||
1226 | |||
1227 | Native_Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2) | ||
1228 | print ("Native_Tasks_column=", Native_Tasks_column) | ||
1229 | |||
1230 | native_key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_build"] | ||
1231 | i = 0 | ||
1232 | while i < len(native_key_tasks): | ||
1233 | if native_key_tasks[i] not in Native_Tasks_column: | ||
1234 | print ("Error! Missing key task: %s" % native_key_tasks[i]) | ||
1235 | else: | ||
1236 | print ("%s is in tasks" % native_key_tasks[i]) | ||
1237 | i = i + 1 | ||
1238 | |||
1239 | if Native_Tasks_column.index(native_key_tasks[0]) != 0: | ||
1240 | print ("Error! %s is not in the right position" % native_key_tasks[0]) | ||
1241 | else: | ||
1242 | print ("%s is in right position" % native_key_tasks[0]) | ||
1243 | |||
1244 | if Native_Tasks_column[-1] != native_key_tasks[-1]: | ||
1245 | print ("Error! %s is not in the right position" % native_key_tasks[-1]) | ||
1246 | else: | ||
1247 | print ("%s is in right position" % native_key_tasks[-1]) | ||
1248 | |||
1249 | driver.find_element_by_partial_link_text("Packages (").click() | ||
1250 | native_packages_name = driver.find_element_by_partial_link_text("Packages (").text | ||
1251 | print native_packages_name | ||
1252 | native_packages_num = string.atoi(filter(str.isdigit, repr(native_packages_name))) | ||
1253 | print native_packages_num | ||
1254 | |||
1255 | if native_packages_num != 0: | ||
1256 | print ("Error! Native task shouldn't have any packages.") | ||
1257 | else: | ||
1258 | native_package_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text) | ||
1259 | print native_package_message | ||
1260 | if native_package_message.find("does not build any packages.") < 0: | ||
1261 | print ("Error! The message for native task isn't expected.") | ||
1262 | else: | ||
1263 | print ("The message for native task is expected.") | ||
1264 | |||
1265 | driver.find_element_by_partial_link_text("Build dependencies (").click() | ||
1266 | native_depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text | ||
1267 | print native_depends_name | ||
1268 | native_depends_num = string.atoi(filter(str.isdigit, repr(native_depends_name))) | ||
1269 | print native_depends_num | ||
1270 | |||
1271 | native_depends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[3]/table/tbody/tr/td[1]")) | ||
1272 | print native_depends_row_count | ||
1273 | |||
1274 | if native_depends_num != native_depends_row_count: | ||
1275 | print ("Error! The dependent packages number is not correct") | ||
1276 | else: | ||
1277 | print ("The dependent packages number is correct") | ||
1278 | |||
1279 | driver.find_element_by_partial_link_text("Reverse build dependencies (").click() | ||
1280 | native_rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text | ||
1281 | print native_rdepends_name | ||
1282 | native_rdepends_num = string.atoi(filter(str.isdigit, repr(native_rdepends_name))) | ||
1283 | print native_rdepends_num | ||
1284 | |||
1285 | native_rdepends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[4]/table/tbody/tr/td[1]")) | ||
1286 | print native_rdepends_row_count | ||
1287 | |||
1288 | if native_rdepends_num != native_rdepends_row_count: | ||
1289 | print ("Error! The reverse dependent packages number is not correct") | ||
1290 | else: | ||
1291 | print ("The reverse dependent packages number is correct") | ||
1292 | |||
1293 | driver.find_element_by_link_text("Recipes").click() | ||
1294 | |||
1295 | |||
1296 | ############## | ||
1297 | # CASE 915 # | ||
1298 | ############## | ||
1299 | def test_915(self): | ||
1300 | self.case_no = self.get_case_number() | ||
1301 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1302 | self.driver.maximize_window() | ||
1303 | self.driver.get(self.base_url) | ||
1304 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1305 | # step 3 | ||
1306 | self.find_element_by_link_text_in_table('nav', 'Configuration').click() | ||
1307 | self.driver.find_element_by_link_text("BitBake variables").click() | ||
1308 | # step 4 | ||
1309 | self.driver.find_element_by_id("search").clear() | ||
1310 | self.driver.find_element_by_id("search").send_keys("lib") | ||
1311 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1312 | # save screen to see result | ||
1313 | self.browser_delay() | ||
1314 | self.save_screenshot(screenshot_type='selenium', append_name='step4') | ||
1315 | # step 5 | ||
1316 | self.driver.find_element_by_css_selector("i.icon-remove").click() | ||
1317 | head_list = self.get_table_head_text('otable') | ||
1318 | print head_list | ||
1319 | print len(head_list) | ||
1320 | self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description']) | ||
1321 | # step 8 | ||
1322 | # search other string. and click "Variable" to re-sort, check if table | ||
1323 | # head is still the same | ||
1324 | self.driver.find_element_by_id("search").clear() | ||
1325 | self.driver.find_element_by_id("search").send_keys("poky") | ||
1326 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1327 | self.find_element_by_link_text_in_table('otable', 'Variable').click() | ||
1328 | head_list = self.get_table_head_text('otable') | ||
1329 | self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description']) | ||
1330 | self.find_element_by_link_text_in_table('otable', 'Variable').click() | ||
1331 | head_list = self.get_table_head_text('otable') | ||
1332 | self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description']) | ||
1333 | |||
1334 | |||
1335 | ############## | ||
1336 | # CASE 916 # | ||
1337 | ############## | ||
1338 | def test_916(self): | ||
1339 | self.case_no = self.get_case_number() | ||
1340 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1341 | self.driver.maximize_window() | ||
1342 | self.driver.get(self.base_url) | ||
1343 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1344 | # step 2-3 | ||
1345 | self.find_element_by_link_text_in_table('nav', 'Configuration').click() | ||
1346 | self.driver.find_element_by_link_text("BitBake variables").click() | ||
1347 | variable_list = self.get_table_column_text('class', 'variable_name') | ||
1348 | self.failUnless(is_list_sequenced(variable_list)) | ||
1349 | # step 4 | ||
1350 | self.find_element_by_link_text_in_table('otable', 'Variable').click() | ||
1351 | variable_list = self.get_table_column_text('class', 'variable_name') | ||
1352 | self.failUnless(is_list_inverted(variable_list)) | ||
1353 | self.find_element_by_link_text_in_table('otable', 'Variable').click() | ||
1354 | # step 5 | ||
1355 | # searching won't change the sequentiality | ||
1356 | self.driver.find_element_by_id("search").clear() | ||
1357 | self.driver.find_element_by_id("search").send_keys("lib") | ||
1358 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1359 | variable_list = self.get_table_column_text('class', 'variable_name') | ||
1360 | self.failUnless(is_list_sequenced(variable_list)) | ||
1361 | |||
1362 | |||
1363 | ############## | ||
1364 | # CASE 923 # | ||
1365 | ############## | ||
1366 | def test_923(self): | ||
1367 | self.case_no = self.get_case_number() | ||
1368 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1369 | self.driver.maximize_window() | ||
1370 | self.driver.get(self.base_url) | ||
1371 | # Step 2 | ||
1372 | # default sequence in "Completed on" column is inverted | ||
1373 | c_list = self.get_table_column_text('class', 'completed_on') | ||
1374 | self.failUnless(is_list_inverted(c_list)) | ||
1375 | # step 3 | ||
1376 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1377 | self.driver.find_element_by_id("started_on").click() | ||
1378 | self.driver.find_element_by_id("log").click() | ||
1379 | self.driver.find_element_by_id("time").click() | ||
1380 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1381 | head_list = self.get_table_head_text('otable') | ||
1382 | for item in ['Outcome', 'Target', 'Machine', 'Started on', 'Completed on', 'Failed tasks', 'Errors', 'Warnings', 'Warnings', 'Time']: | ||
1383 | self.failUnless(item in head_list) | ||
1384 | |||
1385 | |||
1386 | ############## | ||
1387 | # CASE 924 # | ||
1388 | ############## | ||
1389 | def test_924(self): | ||
1390 | self.case_no = self.get_case_number() | ||
1391 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1392 | self.driver.maximize_window() | ||
1393 | self.driver.get(self.base_url) | ||
1394 | # Please refer to case 924 requirement | ||
1395 | # default sequence in "Completed on" column is inverted | ||
1396 | c_list = self.get_table_column_text('class', 'completed_on') | ||
1397 | self.failUnless(is_list_inverted(c_list)) | ||
1398 | # Step 4 | ||
1399 | # click Errors , order in "Completed on" should be disturbed. Then hide | ||
1400 | # error column to check if order in "Completed on" can be restored | ||
1401 | self.find_element_by_link_text_in_table('otable', 'Errors').click() | ||
1402 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1403 | self.driver.find_element_by_id("errors_no").click() | ||
1404 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1405 | # Note: without time.sleep here, there'll be unpredictable error..TBD | ||
1406 | time.sleep(1) | ||
1407 | c_list = self.get_table_column_text('class', 'completed_on') | ||
1408 | self.failUnless(is_list_inverted(c_list)) | ||
1409 | |||
1410 | |||
1411 | ############## | ||
1412 | # CASE 940 # | ||
1413 | ############## | ||
1414 | def test_940(self): | ||
1415 | self.case_no = self.get_case_number() | ||
1416 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1417 | self.driver.maximize_window() | ||
1418 | self.driver.get(self.base_url) | ||
1419 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1420 | # Step 2-3 | ||
1421 | self.find_element_by_link_text_in_table('nav', 'Packages').click() | ||
1422 | check_head_list = ['Package', 'Package version', 'Size', 'Recipe'] | ||
1423 | head_list = self.get_table_head_text('otable') | ||
1424 | self.failUnless(head_list == check_head_list) | ||
1425 | # Step 4 | ||
1426 | # pulldown menu | ||
1427 | option_ids = ['recipe__layer_version__layer__name', 'recipe__layer_version__branch', \ | ||
1428 | 'recipe__layer_version__layer__commit', 'recipe__layer_version__layer__local_path', \ | ||
1429 | 'license', 'recipe__version'] | ||
1430 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1431 | for item in option_ids: | ||
1432 | if not self.driver.find_element_by_id(item).is_selected(): | ||
1433 | self.driver.find_element_by_id(item).click() | ||
1434 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1435 | # save screen here to observe that 'Package' and 'Package version' is | ||
1436 | # not selectable | ||
1437 | self.browser_delay() | ||
1438 | self.save_screenshot(screenshot_type='selenium', append_name='step4') | ||
1439 | |||
1440 | |||
1441 | ############## | ||
1442 | # CASE 941 # | ||
1443 | ############## | ||
1444 | def test_941(self): | ||
1445 | self.case_no = self.get_case_number() | ||
1446 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1447 | self.driver.maximize_window() | ||
1448 | self.driver.get(self.base_url) | ||
1449 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1450 | # Step 2-3 | ||
1451 | self.find_element_by_link_text_in_table('nav', 'Packages').click() | ||
1452 | # column -- Package | ||
1453 | column_list = self.get_table_column_text_by_column_number('otable', 1) | ||
1454 | self.failUnless(is_list_sequenced(column_list)) | ||
1455 | self.find_element_by_link_text_in_table('otable', 'Size').click() | ||
1456 | |||
1457 | |||
1458 | ############## | ||
1459 | # CASE 944 # | ||
1460 | ############## | ||
1461 | def test_944(self): | ||
1462 | self.case_no = self.get_case_number() | ||
1463 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1464 | self.driver.maximize_window() | ||
1465 | self.driver.get(self.base_url) | ||
1466 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1467 | # step 1: test Recipes page stuff | ||
1468 | self.driver.find_element_by_link_text("Recipes").click() | ||
1469 | # for these 3 items, default status is not-checked | ||
1470 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1471 | self.driver.find_element_by_id("layer_version__branch").click() | ||
1472 | self.driver.find_element_by_id("layer_version__layer__commit").click() | ||
1473 | self.driver.find_element_by_id("layer_version__layer__local_path").click() | ||
1474 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1475 | # otable is the recipes table here | ||
1476 | otable_head_text = self.get_table_head_text('otable') | ||
1477 | for item in ["Layer", "Layer branch", "Layer commit", "Layer directory"]: | ||
1478 | self.failIf(item not in otable_head_text) | ||
1479 | # click the fist recipe, whatever it is | ||
1480 | self.get_table_element("otable", 1, 1).click() | ||
1481 | self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Layer directory", "Recipe file"])) | ||
1482 | |||
1483 | # step 2: test Packages page stuff. almost same as above | ||
1484 | self.driver.back() | ||
1485 | self.browser_delay() | ||
1486 | self.driver.find_element_by_link_text("Packages").click() | ||
1487 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1488 | self.driver.find_element_by_id("recipe__layer_version__layer__name").click() | ||
1489 | self.driver.find_element_by_id("recipe__layer_version__branch").click() | ||
1490 | self.driver.find_element_by_id("recipe__layer_version__layer__commit").click() | ||
1491 | self.driver.find_element_by_id("recipe__layer_version__layer__local_path").click() | ||
1492 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1493 | otable_head_text = self.get_table_head_text("otable") | ||
1494 | for item in ["Layer", "Layer branch", "Layer commit", "Layer directory"]: | ||
1495 | self.failIf(item not in otable_head_text) | ||
1496 | # click the fist recipe, whatever it is | ||
1497 | self.get_table_element("otable", 1, 1).click() | ||
1498 | self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Layer directory"])) | ||
1499 | |||
1500 | # step 3: test Packages core-image-minimal(images) stuff. almost same as above. Note when future element-id changes... | ||
1501 | self.driver.back() | ||
1502 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1503 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1504 | self.driver.find_element_by_id("layer_name").click() | ||
1505 | self.driver.find_element_by_id("layer_branch").click() | ||
1506 | self.driver.find_element_by_id("layer_commit").click() | ||
1507 | self.driver.find_element_by_id("layer_directory").click() | ||
1508 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1509 | otable_head_text = self.get_table_head_text("otable") | ||
1510 | for item in ["Layer", "Layer branch", "Layer commit", "Layer directory"]: | ||
1511 | self.failIf(item not in otable_head_text) | ||
1512 | # click the fist recipe, whatever it is | ||
1513 | self.get_table_element("otable", 1, 1).click() | ||
1514 | self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Layer directory"])) | ||
1515 | |||
1516 | # step 4: check Configuration page | ||
1517 | self.driver.back() | ||
1518 | self.driver.find_element_by_link_text("Configuration").click() | ||
1519 | otable_head_text = self.get_table_head_text() | ||
1520 | for item in ["Layer", "Layer branch", "Layer commit", "Layer directory"]: | ||
1521 | self.failIf(item not in otable_head_text) | ||
1522 | |||
1523 | |||
1524 | ############## | ||
1525 | # CASE 945 # | ||
1526 | ############## | ||
1527 | def test_945(self): | ||
1528 | self.case_no = self.get_case_number() | ||
1529 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1530 | self.driver.maximize_window() | ||
1531 | for items in ["Packages", "Recipes", "Tasks"]: | ||
1532 | self.driver.get(self.base_url) | ||
1533 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1534 | self.driver.find_element_by_link_text(items).click() | ||
1535 | |||
1536 | # this may be page specific. If future page content changes, try to replace it with new xpath | ||
1537 | xpath_showrows = "/html/body/div[2]/div/div[2]/div[2]/div[2]/div/div/div[2]/select" | ||
1538 | xpath_table = "/html/body/div[2]/div/div[2]/div[2]/table/tbody" | ||
1539 | self.driver.find_element_by_xpath(xpath_showrows).click() | ||
1540 | rows_displayed = int(self.driver.find_element_by_xpath(xpath_showrows + "/option[2]").text) | ||
1541 | |||
1542 | # not sure if this is a Selenium Select bug: If page is not refreshed here, "select(by visible text)" operation will go back to 100-row page | ||
1543 | # Sure we can use driver.get(url) to refresh page, but since page will vary, we use click link text here | ||
1544 | self.driver.find_element_by_link_text(items).click() | ||
1545 | Select(self.driver.find_element_by_css_selector("select.pagesize")).select_by_visible_text(str(rows_displayed)) | ||
1546 | self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]")) | ||
1547 | self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]")) | ||
1548 | |||
1549 | # click 1st package, then go back to check if it's still those rows shown. | ||
1550 | self.driver.find_element_by_xpath(xpath_table + "/tr[1]/td[1]").click() | ||
1551 | self.driver.find_element_by_link_text(items).click() | ||
1552 | self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]")) | ||
1553 | self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]")) | ||
1554 | |||
1555 | |||
1556 | ############## | ||
1557 | # CASE 946 # | ||
1558 | ############## | ||
1559 | def test_946(self): | ||
1560 | self.case_no = self.get_case_number() | ||
1561 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1562 | self.driver.maximize_window() | ||
1563 | self.driver.get(self.base_url) | ||
1564 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1565 | self.driver.find_element_by_link_text("Configuration").click() | ||
1566 | # step 3-4 | ||
1567 | check_list = ["Summary", "BitBake variables"] | ||
1568 | for item in check_list: | ||
1569 | if not self.is_element_present(how=By.LINK_TEXT, what=item): | ||
1570 | self.log.error("%s not found" %item) | ||
1571 | if not self.is_text_present(['Layers', 'Layer', 'Layer branch', 'Layer commit', 'Layer directory']): | ||
1572 | self.log.error("text not found") | ||
1573 | # step 5 | ||
1574 | self.driver.find_element_by_link_text("BitBake variables").click() | ||
1575 | if not self.is_text_present(['Variable', 'Value', 'Set in file', 'Description']): | ||
1576 | self.log.error("text not found") | ||
1577 | # This may be unstable because it's page-specific | ||
1578 | # step 6: this is how we find filter beside "Set in file" | ||
1579 | temp_element = self.find_element_by_text_in_table('otable', "Set in file") | ||
1580 | temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click() | ||
1581 | self.browser_delay() | ||
1582 | self.driver.find_element_by_xpath("(//input[@name='filter'])[2]").click() | ||
1583 | self.driver.find_element_by_css_selector("button.btn.btn-primary").click() | ||
1584 | # save screen here | ||
1585 | self.browser_delay() | ||
1586 | self.save_screenshot(screenshot_type='selenium', append_name='step6') | ||
1587 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1588 | # save screen here | ||
1589 | # step 7 | ||
1590 | # we should manually check the step 6-8 result using screenshot | ||
1591 | self.browser_delay() | ||
1592 | self.save_screenshot(screenshot_type='selenium', append_name='step7') | ||
1593 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1594 | # step 9 | ||
1595 | # click the 1st item, no matter what it is | ||
1596 | self.driver.find_element_by_xpath("//*[@id='otable']/tbody/tr[1]/td[1]/a").click() | ||
1597 | # give it 1 sec so the pop-up becomes the "active_element" | ||
1598 | time.sleep(1) | ||
1599 | element = self.driver.switch_to.active_element | ||
1600 | check_list = ['Order', 'Configuration file', 'Operation', 'Line number'] | ||
1601 | for item in check_list: | ||
1602 | if item not in element.text: | ||
1603 | self.log.error("%s not found" %item) | ||
1604 | # any better way to close this pop-up? ... TBD | ||
1605 | element.find_element_by_xpath(".//*[@class='close']").click() | ||
1606 | # step 10 : need to manually check "Yocto Manual" in saved screen | ||
1607 | self.driver.find_element_by_css_selector("i.icon-share.get-info").click() | ||
1608 | # save screen here | ||
1609 | time.sleep(5) | ||
1610 | self.save_screenshot(screenshot_type='native', append_name='step10') | ||
1611 | |||
1612 | |||
1613 | ############## | ||
1614 | # CASE 947 # | ||
1615 | ############## | ||
1616 | def test_947(self): | ||
1617 | self.case_no = self.get_case_number() | ||
1618 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1619 | self.driver.maximize_window() | ||
1620 | self.driver.get(self.base_url) | ||
1621 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1622 | self.find_element_by_link_text_in_table('nav', 'Configuration').click() | ||
1623 | # step 2 | ||
1624 | self.driver.find_element_by_link_text("BitBake variables").click() | ||
1625 | # step 3 | ||
1626 | def xpath_option(column_name): | ||
1627 | # return xpath of options under "Edit columns" button | ||
1628 | return self.shortest_xpath('id', 'navTab') + self.shortest_xpath('id', 'editcol') \ | ||
1629 | + self.shortest_xpath('id', column_name) | ||
1630 | self.find_element_by_xpath_in_table('navTab', self.shortest_xpath('class', 'btn dropdown-toggle')).click() | ||
1631 | # by default, option "Description" and "Set in file" were checked | ||
1632 | self.driver.find_element_by_xpath(xpath_option('description')).click() | ||
1633 | self.driver.find_element_by_xpath(xpath_option('file')).click() | ||
1634 | self.find_element_by_xpath_in_table('navTab', self.shortest_xpath('class', 'btn dropdown-toggle')).click() | ||
1635 | check_list = ['Description', 'Set in file'] | ||
1636 | head_list = self.get_table_head_text('otable') | ||
1637 | for item in check_list: | ||
1638 | self.failIf(item in head_list) | ||
1639 | # check these 2 options and verify again | ||
1640 | self.find_element_by_xpath_in_table('navTab', self.shortest_xpath('class', 'btn dropdown-toggle')).click() | ||
1641 | self.driver.find_element_by_xpath(xpath_option('description')).click() | ||
1642 | self.driver.find_element_by_xpath(xpath_option('file')).click() | ||
1643 | self.find_element_by_xpath_in_table('navTab', self.shortest_xpath('class', 'btn dropdown-toggle')).click() | ||
1644 | head_list = self.get_table_head_text('otable') | ||
1645 | for item in check_list: | ||
1646 | self.failUnless(item in head_list) | ||
1647 | |||
1648 | |||
1649 | ############## | ||
1650 | # CASE 948 # | ||
1651 | ############## | ||
1652 | def test_948(self): | ||
1653 | self.case_no = self.get_case_number() | ||
1654 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1655 | self.driver.maximize_window() | ||
1656 | self.driver.get(self.base_url) | ||
1657 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1658 | self.find_element_by_link_text_in_table('nav', 'Configuration').click() | ||
1659 | self.driver.find_element_by_link_text("BitBake variables").click() | ||
1660 | number_before_search = list() | ||
1661 | number_after_search = list() | ||
1662 | # step 3 | ||
1663 | # temp_dict -- filter string : filter name in firepath | ||
1664 | temp_dict = {'Set in file':'filter_vhistory__file_name', 'Description':'filter_description'} | ||
1665 | count = 0 | ||
1666 | for key in temp_dict: | ||
1667 | try: | ||
1668 | temp_element = self.find_element_by_text_in_table('otable', key) | ||
1669 | temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click() | ||
1670 | # delay here. otherwise it won't get correct "text" we need. | ||
1671 | # TBD | ||
1672 | time.sleep(1) | ||
1673 | # step 4-5, we need to make sure that "search" manipulation | ||
1674 | # does reduce the number in the filter. | ||
1675 | # in this case, text returned will be "All variables (xxx)" | ||
1676 | temp_text = self.driver.find_element_by_xpath("//*[@id='" + temp_dict[key] + "']//*[@class='radio']").text | ||
1677 | number_list = extract_number_from_string(temp_text) | ||
1678 | print number_list | ||
1679 | # probably we only need the first number. in this case. | ||
1680 | number_before_search.append(eval(number_list[0])) | ||
1681 | count +=1 | ||
1682 | # how we locate the close button | ||
1683 | self.driver.find_element_by_xpath("//*[@id='" + temp_dict[key] + "']//*[@class='close']").click() | ||
1684 | self.browser_delay() | ||
1685 | except Exception,e: | ||
1686 | self.log.error(e) | ||
1687 | raise | ||
1688 | # search for a while... | ||
1689 | self.driver.find_element_by_id("search").clear() | ||
1690 | self.driver.find_element_by_id("search").send_keys("BB") | ||
1691 | self.driver.find_element_by_css_selector("button.btn").click() | ||
1692 | # same operation as above, only to get the new numbers in the filter | ||
1693 | count = 0 | ||
1694 | for key in temp_dict: | ||
1695 | try: | ||
1696 | temp_element = self.find_element_by_text_in_table('otable', key) | ||
1697 | temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click() | ||
1698 | time.sleep(1) | ||
1699 | # in this case, text returned will be "All variables (xxx)" | ||
1700 | temp_text = self.driver.find_element_by_xpath("//*[@id='" + temp_dict[key] + "']//*[@class='radio']").text | ||
1701 | number_list = extract_number_from_string(temp_text) | ||
1702 | # probably we only need the first number. in this case. | ||
1703 | number_after_search.append(eval(number_list[0])) | ||
1704 | count += 1 | ||
1705 | # how we locate the close button | ||
1706 | self.driver.find_element_by_xpath("//*[@id='" + temp_dict[key] + "']//*[@class='close']").click() | ||
1707 | self.browser_delay() | ||
1708 | except Exception,e: | ||
1709 | self.log.error(e) | ||
1710 | raise | ||
1711 | for i in range(0, count): | ||
1712 | print i | ||
1713 | print number_after_search[i] | ||
1714 | print number_before_search[i] | ||
1715 | if number_after_search[i] < number_before_search[i]: | ||
1716 | self.log.info("After search, filter number reduces") | ||
1717 | else: | ||
1718 | self.log.error("Error: After search, filter number doesn't reduce") | ||
1719 | self.failIf(True) | ||
1720 | |||
1721 | |||
1722 | ############## | ||
1723 | # CASE 949 # | ||
1724 | ############## | ||
1725 | def test_949(self): | ||
1726 | self.case_no = self.get_case_number() | ||
1727 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1728 | self.driver.maximize_window() | ||
1729 | self.driver.get(self.base_url) | ||
1730 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1731 | self.find_element_by_link_text_in_table('nav', 'core-image-minimal').click() | ||
1732 | # step 3 | ||
1733 | try: | ||
1734 | self.driver.find_element_by_partial_link_text("Packages included") | ||
1735 | self.driver.find_element_by_partial_link_text("Directory structure") | ||
1736 | except Exception,e: | ||
1737 | self.log.error(e) | ||
1738 | self.failIf(True) | ||
1739 | # step 4 | ||
1740 | head_list = self.get_table_head_text('otable') | ||
1741 | for item in ['Package', 'Package version', 'Size', 'Dependencies', 'Reverse dependencies', 'Recipe']: | ||
1742 | self.failUnless(item in head_list) | ||
1743 | # step 5-6 | ||
1744 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1745 | selectable_class = 'checkbox' | ||
1746 | # minimum-table : means unselectable items | ||
1747 | unselectable_class = 'checkbox muted' | ||
1748 | selectable_check_list = ['Dependencies', 'Layer', 'Layer branch', 'Layer commit', 'Layer directory', \ | ||
1749 | 'License', 'Recipe', 'Recipe version', 'Reverse dependencies', \ | ||
1750 | 'Size', 'Size over total (%)'] | ||
1751 | unselectable_check_list = ['Package', 'Package version'] | ||
1752 | selectable_list = list() | ||
1753 | unselectable_list = list() | ||
1754 | selectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + selectable_class + "']") | ||
1755 | unselectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + unselectable_class + "']") | ||
1756 | for element in selectable_elements: | ||
1757 | selectable_list.append(element.text) | ||
1758 | for element in unselectable_elements: | ||
1759 | unselectable_list.append(element.text) | ||
1760 | # check them | ||
1761 | for item in selectable_check_list: | ||
1762 | if item not in selectable_list: | ||
1763 | self.log.error(" %s not found in dropdown menu \n" % item) | ||
1764 | self.failIf(True) | ||
1765 | for item in unselectable_check_list: | ||
1766 | if item not in unselectable_list: | ||
1767 | self.log.error(" %s not found in dropdown menu \n" % item) | ||
1768 | self.failIf(True) | ||
1769 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1770 | # step 7 | ||
1771 | self.driver.find_element_by_partial_link_text("Directory structure").click() | ||
1772 | head_list = self.get_table_head_text('dirtable') | ||
1773 | for item in ['Directory / File', 'Symbolic link to', 'Source package', 'Size', 'Permissions', 'Owner', 'Group']: | ||
1774 | if item not in head_list: | ||
1775 | self.log.error(" %s not found in Directory structure table head \n" % item) | ||
1776 | self.failIf(True) | ||
1777 | |||
1778 | |||
1779 | ############## | ||
1780 | # CASE 950 # | ||
1781 | ############## | ||
1782 | def test_950(self): | ||
1783 | self.case_no = self.get_case_number() | ||
1784 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1785 | self.driver.maximize_window() | ||
1786 | self.driver.get(self.base_url) | ||
1787 | # step3&4: so far we're not sure if there's "successful build" or "failed | ||
1788 | # build".If either of them doesn't exist, we can still go on other steps | ||
1789 | check_list = ['Configuration', 'Tasks', 'Recipes', 'Packages', 'Time', 'CPU usage', 'Disk I/O'] | ||
1790 | has_successful_build = 1 | ||
1791 | has_failed_build = 1 | ||
1792 | try: | ||
1793 | pass_icon = self.driver.find_element_by_xpath("//*[@class='icon-ok-sign success']") | ||
1794 | except Exception: | ||
1795 | self.log.info("no successful build exists") | ||
1796 | has_successful_build = 0 | ||
1797 | pass | ||
1798 | if has_successful_build: | ||
1799 | pass_icon.click() | ||
1800 | # save screen here to check if it matches requirement. | ||
1801 | self.browser_delay() | ||
1802 | self.save_screenshot(screenshot_type='selenium', append_name='step3_1') | ||
1803 | for item in check_list: | ||
1804 | try: | ||
1805 | self.find_element_by_link_text_in_table('nav', item) | ||
1806 | except Exception: | ||
1807 | self.log.error("link %s cannot be found in the page" % item) | ||
1808 | self.failIf(True) | ||
1809 | # step 6 | ||
1810 | check_list_2 = ['Packages included', 'Total package size', \ | ||
1811 | 'License manifest', 'Image files'] | ||
1812 | self.failUnless(self.is_text_present(check_list_2)) | ||
1813 | self.driver.back() | ||
1814 | try: | ||
1815 | fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']") | ||
1816 | except Exception: | ||
1817 | has_failed_build = 0 | ||
1818 | self.log.info("no failed build exists") | ||
1819 | pass | ||
1820 | if has_failed_build: | ||
1821 | fail_icon.click() | ||
1822 | # save screen here to check if it matches requirement. | ||
1823 | self.browser_delay() | ||
1824 | self.save_screenshot(screenshot_type='selenium', append_name='step3_2') | ||
1825 | for item in check_list: | ||
1826 | try: | ||
1827 | self.find_element_by_link_text_in_table('nav', item) | ||
1828 | except Exception: | ||
1829 | self.log.error("link %s cannot be found in the page" % item) | ||
1830 | self.failIf(True) | ||
1831 | # step 7 involved | ||
1832 | check_list_3 = ['Machine', 'Distro', 'Layers', 'Total number of tasks', 'Tasks executed', \ | ||
1833 | 'Tasks not executed', 'Reuse', 'Recipes built', 'Packages built'] | ||
1834 | self.failUnless(self.is_text_present(check_list_3)) | ||
1835 | self.driver.back() | ||
1836 | |||
1837 | |||
1838 | ############## | ||
1839 | # CASE 951 # | ||
1840 | ############## | ||
1841 | def test_951(self): | ||
1842 | self.case_no = self.get_case_number() | ||
1843 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1844 | self.driver.maximize_window() | ||
1845 | self.driver.get(self.base_url) | ||
1846 | # currently test case itself isn't responsible for creating "1 successful and | ||
1847 | # 1 failed build" | ||
1848 | has_successful_build = 1 | ||
1849 | has_failed_build = 1 | ||
1850 | try: | ||
1851 | fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']") | ||
1852 | except Exception: | ||
1853 | has_failed_build = 0 | ||
1854 | self.log.info("no failed build exists") | ||
1855 | pass | ||
1856 | # if there's failed build, we can proceed | ||
1857 | if has_failed_build: | ||
1858 | self.driver.find_element_by_partial_link_text("error").click() | ||
1859 | self.driver.back() | ||
1860 | # not sure if there "must be" some warnings, so here save a screen | ||
1861 | self.browser_delay() | ||
1862 | self.save_screenshot(screenshot_type='selenium', append_name='step4') | ||
1863 | |||
1864 | |||
1865 | ############## | ||
1866 | # CASE 955 # | ||
1867 | ############## | ||
1868 | def test_955(self): | ||
1869 | self.case_no = self.get_case_number() | ||
1870 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1871 | self.driver.maximize_window() | ||
1872 | self.driver.get(self.base_url) | ||
1873 | self.log.info(" You should manually create all images before test starts!") | ||
1874 | # So far the case itself is not responsable for creating all sorts of images. | ||
1875 | # So assuming they are already there | ||
1876 | # step 2 | ||
1877 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1878 | # save screen here to see the page component | ||
1879 | |||
1880 | |||
1881 | ############## | ||
1882 | # CASE 956 # | ||
1883 | ############## | ||
1884 | def test_956(self): | ||
1885 | self.case_no = self.get_case_number() | ||
1886 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1887 | self.driver.maximize_window() | ||
1888 | self.driver.get(self.base_url) | ||
1889 | # step 2-3 need to run manually | ||
1890 | self.log.info("step 2-3: checking the help message when you hover on help icon of target,\ | ||
1891 | tasks, recipes, packages need to run manually") | ||
1892 | self.driver.find_element_by_partial_link_text("Toaster manual").click() | ||
1893 | if not self.is_text_present("Toaster Manual"): | ||
1894 | self.log.error("please check [Toaster manual] link on page") | ||
1895 | self.failIf(True) | ||
1896 | |||
1897 | |||
1898 | ############## | ||
1899 | # CASE 959 # | ||
1900 | ############## | ||
1901 | def test_959(self): | ||
1902 | self.case_no = self.get_case_number() | ||
1903 | self.log.info(' CASE %s log: ' % str(self.case_no)) | ||
1904 | self.driver.maximize_window() | ||
1905 | self.driver.get(self.base_url) | ||
1906 | self.driver.find_element_by_link_text("core-image-minimal").click() | ||
1907 | # step 2-3 | ||
1908 | self.find_element_by_link_text_in_table('nav', 'Tasks').click() | ||
1909 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1910 | self.driver.find_element_by_id("task_log").click() | ||
1911 | self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click() | ||
1912 | # step 4: "Not Executed" tasks have no log. So click "Log"... | ||
1913 | self.find_element_by_link_text_in_table('otable', 'Log').click() | ||
1914 | # save screen to see if there's "absolute path" of logs | ||
1915 | self.browser_delay() | ||
1916 | self.save_screenshot(screenshot_type='selenium', append_name='step4_1') | ||
1917 | self.find_element_by_link_text_in_table('otable', 'Log').click() | ||
1918 | # save screen to see if there's "absolute path" of logs | ||
1919 | self.browser_delay() | ||
1920 | self.save_screenshot(screenshot_type='selenium', append_name='step4_2') | ||
1921 | |||
1922 | |||
1923 | |||
1924 | |||