blob: 2a2078f08021e3050519b8ed365dad3022193f42 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#!/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
25import unittest, time, re, sys, getopt, os, logging, string, errno, exceptions
26import shutil, argparse, ConfigParser, platform
27from selenium import webdriver
28from selenium.common.exceptions import NoSuchElementException
29from selenium import selenium
30from selenium.webdriver.common.by import By
31from selenium.webdriver.common.keys import Keys
32from selenium.webdriver.support.ui import Select
33
34
35###########################################
36# #
37# PART I: utils stuff #
38# #
39###########################################
40
41class 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
54def 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
69def 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
79def 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
109def 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
158def 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
206def 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
218def 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
232class 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
596class 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_id("edit-columns-button").click()
609 # adding explicitly wait for chromedriver..-_-
610 self.browser_delay()
611 self.driver.find_element_by_id("started_on").click()
612 self.browser_delay()
613 self.driver.find_element_by_id("time").click()
614 self.driver.find_element_by_id("edit-columns-button").click()
615 # dict: {lint text name : actual class name}
616 table_head_dict = {'Outcome':'outcome', 'Recipe':'target', 'Machine':'machine', 'Started on':'started_on', 'Completed on':'completed_on', \
617 'Errors':'errors_no', 'Warnings':'warnings_no', 'Time':'time'}
618 for key in table_head_dict:
619 try:
620 self.driver.find_element_by_link_text(key).click()
621 except Exception, e:
622 self.log.error("%s cannot be found on page" % key)
623 raise
624 column_list = self.get_table_column_text("class", table_head_dict[key])
625 # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
626 # the point is, after another click, it should be another order
627 if is_list_inverted(column_list):
628 self.driver.find_element_by_link_text(key).click()
629 column_list = self.get_table_column_text("class", table_head_dict[key])
630 self.failUnless(is_list_sequenced(column_list))
631 else:
632 self.failUnless(is_list_sequenced(column_list))
633 self.driver.find_element_by_link_text(key).click()
634 column_list = self.get_table_column_text("class", table_head_dict[key])
635 self.failUnless(is_list_inverted(column_list))
636 self.log.info("case passed")
637
638
639 ##############
640 # CASE 902 #
641 ##############
642 def test_902(self):
643 self.case_no = self.get_case_number()
644 self.log.info(' CASE %s log: ' % str(self.case_no))
645 self.driver.maximize_window()
646 self.driver.get(self.base_url)
647 # Could add more test patterns here in the future. Also, could search some items other than target column in future..
648 patterns = ["minimal", "sato"]
649 for pattern in patterns:
650 ori_target_column_texts = self.get_table_column_text("class", "target")
651 print ori_target_column_texts
652 self.driver.find_element_by_id("search").clear()
653 self.driver.find_element_by_id("search").send_keys(pattern)
654 self.driver.find_element_by_id("search-button").click()
655 new_target_column_texts = self.get_table_column_text("class", "target")
656 # if nothing found, we still count it as "pass"
657 if new_target_column_texts:
658 for text in new_target_column_texts:
659 self.failUnless(text.find(pattern))
660 self.driver.find_element_by_css_selector("i.icon-remove").click()
661 target_column_texts = self.get_table_column_text("class", "target")
662 self.failUnless(ori_target_column_texts == target_column_texts)
663
664
665 ##############
666 # CASE 903 #
667 ##############
668 def test_903(self):
669 self.case_no = self.get_case_number()
670 self.log.info(' CASE %s log: ' % str(self.case_no))
671 self.driver.maximize_window()
672 self.driver.get(self.base_url)
673 # when opening a new page, "started_on" is not displayed by default
674 self.driver.find_element_by_id("edit-columns-button").click()
675 # currently all the delay are for chrome driver -_-
676 self.browser_delay()
677 self.driver.find_element_by_id("started_on").click()
678 self.driver.find_element_by_id("edit-columns-button").click()
679 # step 4
680 items = ["Outcome", "Completed on", "Started on", "Failed tasks", "Errors", "Warnings"]
681 for item in items:
682 try:
683 temp_element = self.find_element_by_text_in_table('otable', item)
684 # this is how we find "filter icon" in the same level as temp_element(where "a" means clickable, "i" means icon)
685 self.failUnless(temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']"))
686 except Exception,e:
687 self.log.error(" %s cannot be found! %s" % (item, e))
688 self.failIf(True)
689 raise
690 # step 5-6
691 temp_element = self.find_element_by_link_text_in_table('otable', 'Outcome')
692 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
693 self.browser_delay()
694 # the 2nd option, whatever it is
695 self.driver.find_element_by_xpath("(//input[@name='filter'])[2]").click()
696 # click "Apply" button
697 self.driver.find_element_by_xpath("//*[@id='filter_outcome']//*[text()='Apply']").click()
698 # save screen here
699 time.sleep(1)
700 self.save_screenshot(screenshot_type='selenium', append_name='step5')
701 temp_element = self.find_element_by_link_text_in_table('otable', 'Completed on')
702 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
703 self.browser_delay()
704 self.driver.find_element_by_xpath("//*[@id='filter_completed_on']//*[text()='Apply']").click()
705 # save screen here to compare to previous one
706 # please note that for chrome driver, need a little break before saving
707 # screen here -_-
708 self.browser_delay()
709 self.save_screenshot(screenshot_type='selenium', append_name='step6')
710 self.driver.find_element_by_id("search").clear()
711 self.driver.find_element_by_id("search").send_keys("core-image")
712 self.driver.find_element_by_id("search-button").click()
713
714
715 ##############
716 # CASE 904 #
717 ##############
718 def test_904(self):
719 self.case_no = self.get_case_number()
720 self.log.info(' CASE %s log: ' % str(self.case_no))
721 self.driver.maximize_window()
722 self.driver.get(self.base_url)
723 self.driver.find_element_by_partial_link_text("core-image").click()
724 self.driver.find_element_by_link_text("Tasks").click()
725# self.driver.find_element_by_link_text("All builds").click()
726# self.driver.back()
727 self.table_name = 'otable'
728 # This is how we find the "default" rows-number!
729 rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text)
730 print rows_displayed
731 self.failUnless(self.get_table_element(self.table_name, rows_displayed))
732 self.failIf(self.get_table_element(self.table_name, rows_displayed + 1))
733 # Search text box background text is "Search tasks"
734 self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search tasks']"))
735
736 self.driver.find_element_by_id("search").clear()
737 self.driver.find_element_by_id("search").send_keys("busybox")
738 self.driver.find_element_by_id("search-button").click()
739 self.browser_delay()
740 self.save_screenshot(screenshot_type='selenium', append_name='step5')
741 self.driver.find_element_by_css_selector("i.icon-remove").click()
742 # Save screen here
743 self.save_screenshot(screenshot_type='selenium', append_name='step5_2')
744 self.driver.find_element_by_id("edit-columns-button").click()
745 self.driver.find_element_by_id("cpu_used").click()
746 self.driver.find_element_by_id("disk_io").click()
747 self.driver.find_element_by_id("task_log").click()
748 self.driver.find_element_by_id("recipe_version").click()
749 self.driver.find_element_by_id("time_taken").click()
750 self.driver.find_element_by_css_selector("edit-columns-button").click()
751 # The operation is the same as case901
752 # dict: {lint text name : actual class name}
753 table_head_dict = {'Order':'order', 'Recipe':'recipe_name', 'Task':'task_name', 'Executed':'executed', \
754 'Outcome':'outcome', 'Cache attempt':'cache_attempt', 'Time (secs)':'time_taken', 'CPU usage':'cpu_used', \
755 'Disk I/O (ms)':'disk_io'}
756 for key in table_head_dict:
757# This is tricky here: we are doing so because there may be more than 1
758# same-name link_text in one page. So we only find element inside the table
759 self.find_element_by_link_text_in_table(self.table_name, key).click()
760 column_list = self.get_table_column_text("class", table_head_dict[key])
761# after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
762# the point is, after another click, it should be another order
763# the fist case is special:this means every item in column_list is the same, so
764# after one click, either sequenced or inverted will be fine
765 if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \
766 or (not column_list) :
767 self.find_element_by_link_text_in_table(self.table_name, key).click()
768 column_list = self.get_table_column_text("class", table_head_dict[key])
769 self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list))
770 elif is_list_inverted(column_list):
771 self.find_element_by_link_text_in_table(self.table_name, key).click()
772 column_list = self.get_table_column_text("class", table_head_dict[key])
773 self.failUnless(is_list_sequenced(column_list))
774 else:
775 self.failUnless(is_list_sequenced(column_list))
776 self.find_element_by_link_text_in_table(self.table_name, key).click()
777 column_list = self.get_table_column_text("class", table_head_dict[key])
778 self.failUnless(is_list_inverted(column_list))
779# step 8-10
780 # filter dict: {link text name : filter table name in xpath}
781 filter_dict = {'Executed':'filter_executed', 'Outcome':'filter_outcome', 'Cache attempt':'filter_cache_attempt'}
782 for key in filter_dict:
783 temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
784 # find the filter icon besides it.
785 # And here we must have break (1 sec) to get the popup stuff
786 temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
787 self.browser_delay()
788 avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
789 for number in range(0, len(avail_options)):
790 avail_options[number].click()
791 self.browser_delay()
792 # click "Apply"
793 self.driver.find_element_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@type='submit']").click()
794 # insert screen capture here
795 self.browser_delay()
796 self.save_screenshot(screenshot_type='selenium', append_name='step8')
797 # after the last option was clicked, we don't need operation below anymore
798 if number < len(avail_options)-1:
799 temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
800 temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
801 avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
802 self.browser_delay()
803# step 11
804 for item in ['order', 'task_name', 'executed', 'outcome', 'recipe_name', 'recipe_version']:
805 try:
806 self.find_element_by_xpath_in_table(self.table_name, "./tbody/tr[1]/*[@class='" + item + "']/a").click()
807 except NoSuchElementException, e:
808 # let it go...
809 print 'no item in the colum' + item
810 # insert screen shot here
811 self.save_screenshot(screenshot_type='selenium', append_name='step11')
812 self.driver.back()
813# step 12-14
814 # about test_dict: please refer to testcase 904 requirement step 12-14
815 test_dict = {
816 'Time':{
817 'class':'time_taken',
818 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Time (secs)'],
819 'check_column_list':['cpu_used', 'cache_attempt', 'disk_io', 'order', 'recipe_version']
820 },
821 'CPU usage':{
822 'class':'cpu_used',
823 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'CPU usage'],
824 'check_column_list':['cache_attempt', 'disk_io', 'order', 'recipe_version', 'time_taken']
825 },
826 'Disk I/O':{
827 'class':'disk_io',
828 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Disk I/O (ms)'],
829 'check_column_list':['cpu_used', 'cache_attempt', 'order', 'recipe_version', 'time_taken']
830 }
831 }
832 for key in test_dict:
833 self.find_element_by_partial_link_text_in_table('nav', 'core-image').click()
834 self.find_element_by_link_text_in_table('nav', key).click()
835 head_list = self.get_table_head_text('otable')
836 for item in test_dict[key]['check_head_list']:
837 self.failUnless(item in head_list)
838 column_list = self.get_table_column_text('class', test_dict[key]['class'])
839 self.failUnless(is_list_inverted(column_list))
840
841 self.driver.find_element_by_id("edit-columns-button").click()
842 for item2 in test_dict[key]['check_column_list']:
843 self.driver.find_element_by_id(item2).click()
844 self.driver.find_element_by_id("edit-columns-button").click()
845 # TBD: save screen here
846
847
848 ##############
849 # CASE 906 #
850 ##############
851 def test_906(self):
852 self.case_no = self.get_case_number()
853 self.log.info(' CASE %s log: ' % str(self.case_no))
854 self.driver.maximize_window()
855 self.driver.get(self.base_url)
856 self.driver.find_element_by_link_text("core-image-minimal").click()
857 self.find_element_by_link_text_in_table('nav', 'Packages').click()
858 # find "bash" in first column (Packages)
859 self.driver.find_element_by_xpath("//*[@id='otable']//td[1]//*[text()='bash']").click()
860 # save sceen here to observe...
861# step 6
862 self.driver.find_element_by_partial_link_text("Generated files").click()
863 head_list = self.get_table_head_text('otable')
864 for item in ['File', 'Size']:
865 self.failUnless(item in head_list)
866 c_list = self.get_table_column_text('class', 'path')
867 self.failUnless(is_list_sequenced(c_list))
868# step 7
869 self.driver.find_element_by_partial_link_text("Runtime dependencies").click()
870 # save sceen here to observe...
871 # note that here table name is not 'otable'
872 head_list = self.get_table_head_text('dependencies')
873 for item in ['Package', 'Version', 'Size']:
874 self.failUnless(item in head_list)
875 c_list = self.get_table_column_text_by_column_number('dependencies', 1)
876 self.failUnless(is_list_sequenced(c_list))
877 texts = ['Size', 'License', 'Recipe', 'Recipe version', 'Layer', \
878 'Layer branch', 'Layer commit', 'Layer directory']
879 self.failUnless(self.is_text_present(texts))
880
881
882 ##############
883 # CASE 910 #
884 ##############
885 def test_910(self):
886 self.case_no = self.get_case_number()
887 self.log.info(' CASE %s log: ' % str(self.case_no))
888 image_type="core-image-minimal"
889 test_package1="busybox"
890 test_package2="lib"
891 self.driver.maximize_window()
892 self.driver.get(self.base_url)
893 self.driver.find_element_by_link_text(image_type).click()
894 self.driver.find_element_by_link_text("Recipes").click()
895 self.save_screenshot(screenshot_type='selenium', append_name='step3')
896
897 self.table_name = 'otable'
898 # This is how we find the "default" rows-number!
899 rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text)
900 print rows_displayed
901 self.failUnless(self.get_table_element(self.table_name, rows_displayed))
902 self.failIf(self.get_table_element(self.table_name, rows_displayed + 1))
903
904 # Check the default table is sorted by Recipe
905 tasks_column_count = len(self.driver.find_elements_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr/td[1]"))
906 print tasks_column_count
907 default_column_list = self.get_table_column_text_by_column_number(self.table_name, 1)
908 #print default_column_list
909
910 self.failUnless(is_list_sequenced(default_column_list))
911
912 # Search text box background text is "Search recipes"
913 self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
914
915 self.driver.find_element_by_id("search").clear()
916 self.driver.find_element_by_id("search").send_keys(test_package1)
917 self.driver.find_element_by_id("search-button").click()
918 # Save screen here
919 self.save_screenshot(screenshot_type='selenium', append_name='step4')
920 self.driver.find_element_by_css_selector("i.icon-remove").click()
921 self.save_screenshot(screenshot_type='selenium', append_name='step4_2')
922
923 self.driver.find_element_by_id("edit-columns-button").click()
924 self.driver.find_element_by_id("depends_on").click()
925 self.driver.find_element_by_id("layer_version__branch").click()
926 self.driver.find_element_by_id("layer_version__layer__commit").click()
927 self.driver.find_element_by_id("depends_by").click()
928 self.driver.find_element_by_id("edit-columns-button").click()
929
930 self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click()
931 # Check the inverted table by Recipe
932 # Recipe doesn't have class name
933 #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]"))
934 #print inverted_tasks_column_count
935 #inverted_column_list = self.get_table_column_text_by_column_number(self.table_name, 1)
936 #print inverted_column_list
937
938 #self.driver.find_element_by_partial_link_text("zlib").click()
939 #self.driver.back()
940 #self.failUnless(is_list_inverted(inverted_column_list))
941 #self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click()
942
943 table_head_dict = {'Recipe':'recipe__name', 'Recipe file':'recipe_file', 'Section':'recipe_section', \
944 'License':'recipe_license', 'Layer':'layer_version__layer__name', \
945 'Layer branch':'layer_version__branch'}
946 for key in table_head_dict:
947 self.find_element_by_link_text_in_table(self.table_name, key).click()
948 column_list = self.get_table_column_text("class", table_head_dict[key])
949 if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \
950 or (not column_list) :
951 self.find_element_by_link_text_in_table(self.table_name, key).click()
952 column_list = self.get_table_column_text("class", table_head_dict[key])
953 self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list))
954 self.driver.find_element_by_partial_link_text("acl").click()
955 self.driver.back()
956 self.failUnless(is_list_sequenced(column_list) or is_list_inverted(column_list))
957 # Search text box background text is "Search recipes"
958 self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
959 self.driver.find_element_by_id("search").clear()
960 self.driver.find_element_by_id("search").send_keys(test_package2)
961 self.driver.find_element_by_id("search-button").click()
962 column_search_list = self.get_table_column_text("class", table_head_dict[key])
963 self.failUnless(is_list_sequenced(column_search_list) or is_list_inverted(column_search_list))
964 self.driver.find_element_by_css_selector("i.icon-remove").click()
965 elif is_list_inverted(column_list):
966 self.find_element_by_link_text_in_table(self.table_name, key).click()
967 column_list = self.get_table_column_text("class", table_head_dict[key])
968 self.failUnless(is_list_sequenced(column_list))
969 self.driver.find_element_by_partial_link_text("acl").click()
970 self.driver.back()
971 self.failUnless(is_list_sequenced(column_list))
972 # Search text box background text is "Search recipes"
973 self.failUnless(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
974 self.driver.find_element_by_id("search").clear()
975 self.driver.find_element_by_id("search").send_keys(test_package2)
976 self.driver.find_element_by_id("search-button").click()
977 column_search_list = self.get_table_column_text("class", table_head_dict[key])
978 self.failUnless(is_list_sequenced(column_search_list))
979 self.driver.find_element_by_css_selector("i.icon-remove").click()
980 else:
981 self.failUnless(is_list_sequenced(column_list))
982 self.find_element_by_link_text_in_table(self.table_name, key).click()
983 column_list = self.get_table_column_text("class", table_head_dict[key])
984 self.failUnless(is_list_inverted(column_list))
985 try:
986 self.driver.find_element_by_partial_link_text("acl").click()
987 except:
988 self.driver.find_element_by_partial_link_text("zlib").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_id("search-button").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_id("edit-columns-button").click()
1006 self.driver.find_element_by_id(table_head_dict[key]).click()
1007 self.driver.find_element_by_id("edit-columns-button").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_partial_link_text("acl"))
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_id("edit-columns-button").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_id("edit-columns-button").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_id("search-button").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("no such input")
1045 self.driver.find_element_by_id("search-button").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("depends_by").click()
1070 self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
1071 # check if columns selected above is shown
1072 check_list = ['Dependencies', 'Layer branch', 'Layer commit', 'Layer directory', 'Reverse dependencies']
1073 head_list = self.get_table_head_text('otable')
1074 time.sleep(2)
1075 print head_list
1076 for item in check_list:
1077 self.failUnless(item in head_list)
1078 # un-check 'em all
1079 self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
1080 self.driver.find_element_by_id("depends_on").click()
1081 self.driver.find_element_by_id("layer_version__branch").click()
1082 self.driver.find_element_by_id("layer_version__layer__commit").click()
1083 self.driver.find_element_by_id("depends_by").click()
1084 self.driver.find_element_by_css_selector("button.btn.dropdown-toggle").click()
1085 # don't exist any more
1086 head_list = self.get_table_head_text('otable')
1087 for item in check_list:
1088 self.failIf(item in head_list)
1089
1090
1091 ##############
1092 # CASE 913 #
1093 ##############
1094 def test_913(self):
1095 self.case_no = self.get_case_number()
1096 self.log.info(' CASE %s log: ' % str(self.case_no))
1097 self.driver.maximize_window()
1098 self.driver.get(self.base_url)
1099 self.driver.find_element_by_link_text("core-image-minimal").click()
1100 self.find_element_by_link_text_in_table('nav', 'Recipes').click()
1101 # step 3
1102 head_list = self.get_table_head_text('otable')
1103 for item in ['Recipe', 'Recipe version', 'Recipe file', 'Section', 'License', 'Layer']:
1104 self.failUnless(item in head_list)
1105 # step 4
1106 self.driver.find_element_by_id("edit-columns-button").click()
1107 # save screen
1108 self.browser_delay()
1109 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1110 self.driver.find_element_by_id("edit-columns-button").click()
1111
1112
1113 ##############
1114 # CASE 914 #
1115 ##############
1116 def test_914(self):
1117 self.case_no = self.get_case_number()
1118 self.log.info(' CASE %s log: ' % str(self.case_no))
1119 image_type="core-image-minimal"
1120 test_package1="busybox"
1121 test_package2="gdbm"
1122 test_package3="gettext-native"
1123 driver = self.driver
1124 driver.maximize_window()
1125 driver.get(self.base_url)
1126 driver.find_element_by_link_text(image_type).click()
1127 driver.find_element_by_link_text("Recipes").click()
1128 driver.find_element_by_link_text(test_package1).click()
1129
1130 self.table_name = 'information'
1131
1132 tasks_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr/td[1]"))
1133 tasks_column_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr[1]/td"))
1134 print tasks_row_count
1135 print tasks_column_count
1136
1137 Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2)
1138 print ("Tasks_column=", Tasks_column)
1139
1140 key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_package", "do_build"]
1141 i = 0
1142 while i < len(key_tasks):
1143 if key_tasks[i] not in Tasks_column:
1144 print ("Error! Missing key task: %s" % key_tasks[i])
1145 else:
1146 print ("%s is in tasks" % key_tasks[i])
1147 i = i + 1
1148
1149 if Tasks_column.index(key_tasks[0]) != 0:
1150 print ("Error! %s is not in the right position" % key_tasks[0])
1151 else:
1152 print ("%s is in right position" % key_tasks[0])
1153
1154 if Tasks_column[-1] != key_tasks[-1]:
1155 print ("Error! %s is not in the right position" % key_tasks[-1])
1156 else:
1157 print ("%s is in right position" % key_tasks[-1])
1158
1159 driver.find_element_by_partial_link_text("Packages (").click()
1160 packages_name = driver.find_element_by_partial_link_text("Packages (").text
1161 print packages_name
1162 packages_num = string.atoi(filter(str.isdigit, repr(packages_name)))
1163 print packages_num
1164
1165 packages_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[2]/table/tbody/tr/td[1]"))
1166 print packages_row_count
1167
1168 if packages_num != packages_row_count:
1169 print ("Error! The packages number is not correct")
1170 else:
1171 print ("The pakcages number is correct")
1172
1173 driver.find_element_by_partial_link_text("Build dependencies (").click()
1174 depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
1175 print depends_name
1176 depends_num = string.atoi(filter(str.isdigit, repr(depends_name)))
1177 print depends_num
1178
1179 if depends_num == 0:
1180 depends_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text)
1181 print depends_message
1182 if depends_message.find("has no build dependencies.") < 0:
1183 print ("Error! The message isn't expected.")
1184 else:
1185 print ("The message is expected")
1186 else:
1187 depends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[3]/table/tbody/tr/td[1]"))
1188 print depends_row_count
1189 if depends_num != depends_row_count:
1190 print ("Error! The dependent packages number is not correct")
1191 else:
1192 print ("The dependent packages number is correct")
1193
1194 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1195 rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
1196 print rdepends_name
1197 rdepends_num = string.atoi(filter(str.isdigit, repr(rdepends_name)))
1198 print rdepends_num
1199
1200 if rdepends_num == 0:
1201 rdepends_message = repr(driver.find_element_by_css_selector("#brought-in-by > div.alert.alert-info").text)
1202 print rdepends_message
1203 if rdepends_message.find("has no reverse build dependencies.") < 0:
1204 print ("Error! The message isn't expected.")
1205 else:
1206 print ("The message is expected")
1207 else:
1208 print ("The reverse dependent packages number is correct")
1209
1210 driver.find_element_by_link_text("Recipes").click()
1211 driver.find_element_by_link_text(test_package2).click()
1212 driver.find_element_by_partial_link_text("Packages (").click()
1213 driver.find_element_by_partial_link_text("Build dependencies (").click()
1214 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1215
1216
1217 driver.find_element_by_link_text("Recipes").click()
1218 driver.find_element_by_link_text(test_package3).click()
1219
1220 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]"))
1221 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"))
1222 print native_tasks_row_count
1223 print native_tasks_column_count
1224
1225 Native_Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2)
1226 print ("Native_Tasks_column=", Native_Tasks_column)
1227
1228 native_key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_build"]
1229 i = 0
1230 while i < len(native_key_tasks):
1231 if native_key_tasks[i] not in Native_Tasks_column:
1232 print ("Error! Missing key task: %s" % native_key_tasks[i])
1233 else:
1234 print ("%s is in tasks" % native_key_tasks[i])
1235 i = i + 1
1236
1237 if Native_Tasks_column.index(native_key_tasks[0]) != 0:
1238 print ("Error! %s is not in the right position" % native_key_tasks[0])
1239 else:
1240 print ("%s is in right position" % native_key_tasks[0])
1241
1242 if Native_Tasks_column[-1] != native_key_tasks[-1]:
1243 print ("Error! %s is not in the right position" % native_key_tasks[-1])
1244 else:
1245 print ("%s is in right position" % native_key_tasks[-1])
1246
1247 driver.find_element_by_partial_link_text("Packages (").click()
1248 native_packages_name = driver.find_element_by_partial_link_text("Packages (").text
1249 print native_packages_name
1250 native_packages_num = string.atoi(filter(str.isdigit, repr(native_packages_name)))
1251 print native_packages_num
1252
1253 if native_packages_num != 0:
1254 print ("Error! Native task shouldn't have any packages.")
1255 else:
1256 native_package_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text)
1257 print native_package_message
1258 if native_package_message.find("does not build any packages.") < 0:
1259 print ("Error! The message for native task isn't expected.")
1260 else:
1261 print ("The message for native task is expected.")
1262
1263 driver.find_element_by_partial_link_text("Build dependencies (").click()
1264 native_depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
1265 print native_depends_name
1266 native_depends_num = string.atoi(filter(str.isdigit, repr(native_depends_name)))
1267 print native_depends_num
1268
1269 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]"))
1270 print native_depends_row_count
1271
1272 if native_depends_num != native_depends_row_count:
1273 print ("Error! The dependent packages number is not correct")
1274 else:
1275 print ("The dependent packages number is correct")
1276
1277 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1278 native_rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
1279 print native_rdepends_name
1280 native_rdepends_num = string.atoi(filter(str.isdigit, repr(native_rdepends_name)))
1281 print native_rdepends_num
1282
1283 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]"))
1284 print native_rdepends_row_count
1285
1286 if native_rdepends_num != native_rdepends_row_count:
1287 print ("Error! The reverse dependent packages number is not correct")
1288 else:
1289 print ("The reverse dependent packages number is correct")
1290
1291 driver.find_element_by_link_text("Recipes").click()
1292
1293
1294 ##############
1295 # CASE 915 #
1296 ##############
1297 def test_915(self):
1298 self.case_no = self.get_case_number()
1299 self.log.info(' CASE %s log: ' % str(self.case_no))
1300 self.driver.maximize_window()
1301 self.driver.get(self.base_url)
1302 self.driver.find_element_by_link_text("core-image-minimal").click()
1303# step 3
1304 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1305 self.driver.find_element_by_link_text("BitBake variables").click()
1306# step 4
1307 self.driver.find_element_by_id("search").clear()
1308 self.driver.find_element_by_id("search").send_keys("lib")
1309 self.driver.find_element_by_id("search-button").click()
1310 # save screen to see result
1311 self.browser_delay()
1312 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1313# step 5
1314 self.driver.find_element_by_css_selector("i.icon-remove").click()
1315 head_list = self.get_table_head_text('otable')
1316 print head_list
1317 print len(head_list)
1318 self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description'])
1319# step 8
1320 # search other string. and click "Variable" to re-sort, check if table
1321 # head is still the same
1322 self.driver.find_element_by_id("search").clear()
1323 self.driver.find_element_by_id("search").send_keys("poky")
1324 self.driver.find_element_by_id("search-button").click()
1325 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1326 head_list = self.get_table_head_text('otable')
1327 self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description'])
1328 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1329 head_list = self.get_table_head_text('otable')
1330 self.failUnless(head_list == ['Variable', 'Value', 'Set in file', 'Description'])
1331
1332
1333 ##############
1334 # CASE 916 #
1335 ##############
1336 def test_916(self):
1337 self.case_no = self.get_case_number()
1338 self.log.info(' CASE %s log: ' % str(self.case_no))
1339 self.driver.maximize_window()
1340 self.driver.get(self.base_url)
1341 self.driver.find_element_by_link_text("core-image-minimal").click()
1342# step 2-3
1343 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1344 self.driver.find_element_by_link_text("BitBake variables").click()
1345 variable_list = self.get_table_column_text('class', 'variable_name')
1346 self.failUnless(is_list_sequenced(variable_list))
1347# step 4
1348 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1349 variable_list = self.get_table_column_text('class', 'variable_name')
1350 self.failUnless(is_list_inverted(variable_list))
1351 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1352# step 5
1353 # searching won't change the sequentiality
1354 self.driver.find_element_by_id("search").clear()
1355 self.driver.find_element_by_id("search").send_keys("lib")
1356 self.driver.find_element_by_id("search-button").click()
1357 variable_list = self.get_table_column_text('class', 'variable_name')
1358 self.failUnless(is_list_sequenced(variable_list))
1359
1360
1361 ##############
1362 # CASE 923 #
1363 ##############
1364 def test_923(self):
1365 self.case_no = self.get_case_number()
1366 self.log.info(' CASE %s log: ' % str(self.case_no))
1367 self.driver.maximize_window()
1368 self.driver.get(self.base_url)
1369 # Step 2
1370 # default sequence in "Completed on" column is inverted
1371 c_list = self.get_table_column_text('class', 'completed_on')
1372 self.failUnless(is_list_inverted(c_list))
1373 # step 3
1374 self.driver.find_element_by_id("edit-columns-button").click()
1375 self.driver.find_element_by_id("started_on").click()
1376 self.driver.find_element_by_id("log").click()
1377 self.driver.find_element_by_id("time").click()
1378 self.driver.find_element_by_id("edit-columns-button").click()
1379 head_list = self.get_table_head_text('otable')
1380 for item in ['Outcome', 'Target', 'Machine', 'Started on', 'Completed on', 'Failed tasks', 'Errors', 'Warnings', 'Warnings', 'Time']:
1381 self.failUnless(item in head_list)
1382
1383
1384 ##############
1385 # CASE 924 #
1386 ##############
1387 def test_924(self):
1388 self.case_no = self.get_case_number()
1389 self.log.info(' CASE %s log: ' % str(self.case_no))
1390 self.driver.maximize_window()
1391 self.driver.get(self.base_url)
1392 # Please refer to case 924 requirement
1393 # default sequence in "Completed on" column is inverted
1394 c_list = self.get_table_column_text('class', 'completed_on')
1395 self.failUnless(is_list_inverted(c_list))
1396 # Step 4
1397 # click Errors , order in "Completed on" should be disturbed. Then hide
1398 # error column to check if order in "Completed on" can be restored
1399 self.find_element_by_link_text_in_table('otable', 'Errors').click()
1400 self.driver.find_element_by_id("edit-columns-button").click()
1401 self.driver.find_element_by_id("errors_no").click()
1402 self.driver.find_element_by_id("edit-columns-button").click()
1403 # Note: without time.sleep here, there'll be unpredictable error..TBD
1404 time.sleep(1)
1405 c_list = self.get_table_column_text('class', 'completed_on')
1406 self.failUnless(is_list_inverted(c_list))
1407
1408
1409 ##############
1410 # CASE 940 #
1411 ##############
1412 def test_940(self):
1413 self.case_no = self.get_case_number()
1414 self.log.info(' CASE %s log: ' % str(self.case_no))
1415 self.driver.maximize_window()
1416 self.driver.get(self.base_url)
1417 self.driver.find_element_by_link_text("core-image-minimal").click()
1418# Step 2-3
1419 self.find_element_by_link_text_in_table('nav', 'Packages').click()
1420 check_head_list = ['Package', 'Package version', 'Size', 'Recipe']
1421 head_list = self.get_table_head_text('otable')
1422 self.failUnless(head_list == check_head_list)
1423# Step 4
1424 # pulldown menu
1425 option_ids = ['recipe__layer_version__layer__name', 'recipe__layer_version__branch', \
1426 'recipe__layer_version__layer__commit', 'license', 'recipe__version']
1427 self.driver.find_element_by_id("edit-columns-button").click()
1428 for item in option_ids:
1429 if not self.driver.find_element_by_id(item).is_selected():
1430 self.driver.find_element_by_id(item).click()
1431 self.driver.find_element_by_id("edit-columns-button").click()
1432 # save screen here to observe that 'Package' and 'Package version' is
1433 # not selectable
1434 self.browser_delay()
1435 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1436
1437
1438 ##############
1439 # CASE 941 #
1440 ##############
1441 def test_941(self):
1442 self.case_no = self.get_case_number()
1443 self.log.info(' CASE %s log: ' % str(self.case_no))
1444 self.driver.maximize_window()
1445 self.driver.get(self.base_url)
1446 self.driver.find_element_by_link_text("core-image-minimal").click()
1447 # Step 2-3
1448 self.find_element_by_link_text_in_table('nav', 'Packages').click()
1449 # column -- Package
1450 column_list = self.get_table_column_text_by_column_number('otable', 1)
1451 self.failUnless(is_list_sequenced(column_list))
1452 self.find_element_by_link_text_in_table('otable', 'Size').click()
1453
1454
1455 ##############
1456 # CASE 942 #
1457 ##############
1458 def test_942(self):
1459 self.case_no = self.get_case_number()
1460 self.log.info(' CASE %s log: ' % str(self.case_no))
1461 self.driver.maximize_window()
1462 self.driver.get(self.base_url)
1463 self.driver.find_element_by_link_text("core-image-minimal").click()
1464 self.driver.find_element_by_link_text("Packages").click()
1465 #get initial table header
1466 head_list = self.get_table_head_text('otable')
1467 #remove the Recipe column from table header
1468 self.driver.find_element_by_id("edit-columns-button").click()
1469 self.driver.find_element_by_id("recipe__name").click()
1470 self.driver.find_element_by_id("edit-columns-button").click()
1471 #get modified table header
1472 new_head = self.get_table_head_text('otable')
1473 self.failUnless(head_list > new_head)
1474
1475 ##############
1476 # CASE 943 #
1477 ##############
1478 def test_943(self):
1479 self.case_no = self.get_case_number()
1480 self.log.info(' CASE %s log: ' % str(self.case_no))
1481 self.driver.maximize_window()
1482 self.driver.get(self.base_url)
1483 self.driver.find_element_by_link_text("core-image-minimal").click()
1484 self.driver.find_element_by_link_text("Packages").click()
1485 #search for the "bash" package -> this should definitely be present
1486 self.driver.find_element_by_id("search").clear()
1487 self.driver.find_element_by_id("search").send_keys("bash")
1488 self.driver.find_element_by_id("search-button").click()
1489 #check for the search result message "XX packages found"
1490 self.failUnless(self.is_text_present("packages found"))
1491
1492
1493 ##############
1494 # CASE 944 #
1495 ##############
1496 def test_944(self):
1497 self.case_no = self.get_case_number()
1498 self.log.info(' CASE %s log: ' % str(self.case_no))
1499 self.driver.maximize_window()
1500 self.driver.get(self.base_url)
1501 self.driver.find_element_by_link_text("core-image-minimal").click()
1502 # step 1: test Recipes page stuff
1503 self.driver.find_element_by_link_text("Recipes").click()
1504 # for these 3 items, default status is not-checked
1505 self.driver.find_element_by_id("edit-columns-button").click()
1506 self.driver.find_element_by_id("layer_version__branch").click()
1507 self.driver.find_element_by_id("layer_version__layer__commit").click()
1508 self.driver.find_element_by_id("edit-columns-button").click()
1509 # otable is the recipes table here
1510 otable_head_text = self.get_table_head_text('otable')
1511 for item in ["Layer", "Layer branch", "Layer commit", "Layer directory"]:
1512 self.failIf(item not in otable_head_text)
1513 # click the fist recipe, whatever it is
1514 self.get_table_element("otable", 1, 1).click()
1515 self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Recipe file"]))
1516
1517 # step 2: test Packages page stuff. almost same as above
1518 self.driver.back()
1519 self.browser_delay()
1520 self.driver.find_element_by_link_text("Packages").click()
1521 self.driver.find_element_by_id("edit-columns-button").click()
1522 self.driver.find_element_by_id("recipe__layer_version__layer__name").click()
1523 self.driver.find_element_by_id("recipe__layer_version__branch").click()
1524 self.driver.find_element_by_id("recipe__layer_version__layer__commit").click()
1525 self.driver.find_element_by_id("edit-columns-button").click()
1526 otable_head_text = self.get_table_head_text("otable")
1527 for item in ["Layer", "Layer branch", "Layer commit"]:
1528 self.failIf(item not in otable_head_text)
1529 # click the fist recipe, whatever it is
1530 self.get_table_element("otable", 1, 1).click()
1531 self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit"]))
1532
1533 # step 3: test Packages core-image-minimal(images) stuff. almost same as above. Note when future element-id changes...
1534 self.driver.back()
1535 self.driver.find_element_by_link_text("core-image-minimal").click()
1536 self.driver.find_element_by_id("edit-columns-button").click()
1537 self.driver.find_element_by_id("layer_name").click()
1538 self.driver.find_element_by_id("layer_branch").click()
1539 self.driver.find_element_by_id("layer_commit").click()
1540 self.driver.find_element_by_id("edit-columns-button").click()
1541 otable_head_text = self.get_table_head_text("otable")
1542 for item in ["Layer", "Layer branch", "Layer commit"]:
1543 self.failIf(item not in otable_head_text)
1544 # click the fist recipe, whatever it is
1545 self.get_table_element("otable", 1, 1).click()
1546 self.failUnless(self.is_text_present(["Layer", "Layer branch", "Layer commit"]))
1547
1548 # step 4: check Configuration page
1549 self.driver.back()
1550 self.driver.find_element_by_link_text("Configuration").click()
1551 otable_head_text = self.get_table_head_text()
1552 for item in ["Layer", "Layer branch", "Layer commit"]:
1553 self.failIf(item not in otable_head_text)
1554
1555
1556 ##############
1557 # CASE 945 #
1558 ##############
1559 def test_945(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 for items in ["Packages", "Recipes", "Tasks"]:
1564 self.driver.get(self.base_url)
1565 self.driver.find_element_by_link_text("core-image-minimal").click()
1566 self.driver.find_element_by_link_text(items).click()
1567
1568 # this may be page specific. If future page content changes, try to replace it with new xpath
1569 xpath_showrows = "/html/body/div[2]/div/div[2]/div[2]/div[2]/div/div/div[2]/select"
1570 xpath_table = "/html/body/div[2]/div/div[2]/div[2]/table/tbody"
1571 self.driver.find_element_by_xpath(xpath_showrows).click()
1572 rows_displayed = int(self.driver.find_element_by_xpath(xpath_showrows + "/option[2]").text)
1573
1574 # 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
1575 # Sure we can use driver.get(url) to refresh page, but since page will vary, we use click link text here
1576 self.driver.find_element_by_link_text(items).click()
1577 Select(self.driver.find_element_by_css_selector("select.pagesize")).select_by_visible_text(str(rows_displayed))
1578 self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
1579 self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
1580
1581 # click 1st package, then go back to check if it's still those rows shown.
1582 self.driver.find_element_by_xpath(xpath_table + "/tr[1]/td[1]").click()
1583 self.driver.find_element_by_link_text(items).click()
1584 self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
1585 self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
1586
1587
1588 ##############
1589 # CASE 946 #
1590 ##############
1591 def test_946(self):
1592 self.case_no = self.get_case_number()
1593 self.log.info(' CASE %s log: ' % str(self.case_no))
1594 self.driver.maximize_window()
1595 self.driver.get(self.base_url)
1596 self.driver.find_element_by_link_text("core-image-minimal").click()
1597 self.driver.find_element_by_link_text("Configuration").click()
1598 # step 3-4
1599 check_list = ["Summary", "BitBake variables"]
1600 for item in check_list:
1601 if not self.is_element_present(how=By.LINK_TEXT, what=item):
1602 self.log.error("%s not found" %item)
1603 if not self.is_text_present(['Layers', 'Layer', 'Layer branch', 'Layer commit']):
1604 self.log.error("text not found")
1605 # step 5
1606 self.driver.find_element_by_link_text("BitBake variables").click()
1607 if not self.is_text_present(['Variable', 'Value', 'Set in file', 'Description']):
1608 self.log.error("text not found")
1609 # This may be unstable because it's page-specific
1610 # step 6: this is how we find filter beside "Set in file"
1611 temp_element = self.find_element_by_text_in_table('otable', "Set in file")
1612 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
1613 self.browser_delay()
1614 self.driver.find_element_by_xpath("(//input[@name='filter'])[3]").click()
1615 btns = self.driver.find_elements_by_css_selector("button.btn.btn-primary")
1616 for btn in btns:
1617 try:
1618 btn.click()
1619 break
1620 except:
1621 pass
1622 # save screen here
1623 self.browser_delay()
1624 self.save_screenshot(screenshot_type='selenium', append_name='step6')
1625 self.driver.find_element_by_id("edit-columns-button").click()
1626 # save screen here
1627 # step 7
1628 # we should manually check the step 6-8 result using screenshot
1629 self.browser_delay()
1630 self.save_screenshot(screenshot_type='selenium', append_name='step7')
1631 self.driver.find_element_by_id("edit-columns-button").click()
1632 # step 9
1633 # click the 1st item, no matter what it is
1634 self.driver.find_element_by_xpath("//*[@id='otable']/tbody/tr[1]/td[1]/a").click()
1635 # give it 1 sec so the pop-up becomes the "active_element"
1636 time.sleep(1)
1637 element = self.driver.switch_to.active_element
1638 check_list = ['Order', 'Configuration file', 'Operation', 'Line number']
1639 for item in check_list:
1640 if item not in element.text:
1641 self.log.error("%s not found" %item)
1642 # any better way to close this pop-up? ... TBD
1643 element.find_element_by_class_name("close").click()
1644 # step 10 : need to manually check "Yocto Manual" in saved screen
1645 self.driver.find_element_by_css_selector("i.icon-share.get-info").click()
1646 # save screen here
1647 time.sleep(5)
1648 self.save_screenshot(screenshot_type='native', append_name='step10')
1649
1650
1651 ##############
1652 # CASE 947 #
1653 ##############
1654 def test_947(self):
1655 self.case_no = self.get_case_number()
1656 self.log.info(' CASE %s log: ' % str(self.case_no))
1657 self.driver.maximize_window()
1658 self.driver.get(self.base_url)
1659 self.driver.find_element_by_link_text("core-image-minimal").click()
1660 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1661 # step 2
1662 self.driver.find_element_by_link_text("BitBake variables").click()
1663 # step 3
1664 def xpath_option(column_name):
1665 # return xpath of options under "Edit columns" button
1666 return self.shortest_xpath('id', 'navTab') + self.shortest_xpath('id', 'editcol') \
1667 + self.shortest_xpath('id', column_name)
1668 self.driver.find_element_by_id('edit-columns-button').click()
1669 # by default, option "Description" and "Set in file" were checked
1670 self.driver.find_element_by_xpath(xpath_option('description')).click()
1671 self.driver.find_element_by_xpath(xpath_option('file')).click()
1672 self.driver.find_element_by_id('edit-columns-button').click()
1673 check_list = ['Description', 'Set in file']
1674 head_list = self.get_table_head_text('otable')
1675 for item in check_list:
1676 self.failIf(item in head_list)
1677 # check these 2 options and verify again
1678 self.driver.find_element_by_id('edit-columns-button').click()
1679 self.driver.find_element_by_xpath(xpath_option('description')).click()
1680 self.driver.find_element_by_xpath(xpath_option('file')).click()
1681 self.driver.find_element_by_id('edit-columns-button').click()
1682 head_list = self.get_table_head_text('otable')
1683 for item in check_list:
1684 self.failUnless(item in head_list)
1685
1686
1687 ##############
1688 # CASE 948 #
1689 ##############
1690 def test_948(self):
1691 self.case_no = self.get_case_number()
1692 self.log.info(' CASE %s log: ' % str(self.case_no))
1693 self.driver.maximize_window()
1694 self.driver.get(self.base_url)
1695 self.driver.find_element_by_link_text("core-image-minimal").click()
1696 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1697 self.driver.find_element_by_link_text("BitBake variables").click()
1698 #get number of variables visible by default
1699 number_before_search = self.driver.find_element_by_class_name('page-header').text
1700 # search for a while...
1701 self.driver.find_element_by_id("search").clear()
1702 self.driver.find_element_by_id("search").send_keys("BB")
1703 self.driver.find_element_by_id("search-button").click()
1704 #get number of variables visible after search
1705 number_after_search = self.driver.find_element_by_class_name('page-header').text
1706 self.failUnless(number_before_search > number_after_search)
1707
1708
1709 ##############
1710 # CASE 949 #
1711 ##############
1712 def test_949(self):
1713 self.case_no = self.get_case_number()
1714 self.log.info(' CASE %s log: ' % str(self.case_no))
1715 self.driver.maximize_window()
1716 self.driver.get(self.base_url)
1717 self.driver.find_element_by_link_text("core-image-minimal").click()
1718 self.find_element_by_link_text_in_table('nav', 'core-image-minimal').click()
1719 # step 3
1720 try:
1721 self.driver.find_element_by_partial_link_text("Packages included")
1722 self.driver.find_element_by_partial_link_text("Directory structure")
1723 except Exception,e:
1724 self.log.error(e)
1725 self.failIf(True)
1726 # step 4
1727 head_list = self.get_table_head_text('otable')
1728 for item in ['Package', 'Package version', 'Size', 'Dependencies', 'Reverse dependencies', 'Recipe']:
1729 self.failUnless(item in head_list)
1730 # step 5-6
1731 self.driver.find_element_by_id("edit-columns-button").click()
1732 selectable_class = 'checkbox'
1733 # minimum-table : means unselectable items
1734 unselectable_class = 'checkbox muted'
1735 selectable_check_list = ['Dependencies', 'Layer', 'Layer branch', 'Layer commit', \
1736 'License', 'Recipe', 'Recipe version', 'Reverse dependencies', \
1737 'Size', 'Size over total (%)']
1738 unselectable_check_list = ['Package', 'Package version']
1739 selectable_list = list()
1740 unselectable_list = list()
1741 selectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + selectable_class + "']")
1742 unselectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + unselectable_class + "']")
1743 for element in selectable_elements:
1744 selectable_list.append(element.text)
1745 for element in unselectable_elements:
1746 unselectable_list.append(element.text)
1747 # check them
1748 for item in selectable_check_list:
1749 if item not in selectable_list:
1750 self.log.error(" %s not found in dropdown menu \n" % item)
1751 self.failIf(True)
1752 for item in unselectable_check_list:
1753 if item not in unselectable_list:
1754 self.log.error(" %s not found in dropdown menu \n" % item)
1755 self.failIf(True)
1756 self.driver.find_element_by_id("edit-columns-button").click()
1757 # step 7
1758 self.driver.find_element_by_partial_link_text("Directory structure").click()
1759 head_list = self.get_table_head_text('dirtable')
1760 for item in ['Directory / File', 'Symbolic link to', 'Source package', 'Size', 'Permissions', 'Owner', 'Group']:
1761 if item not in head_list:
1762 self.log.error(" %s not found in Directory structure table head \n" % item)
1763 self.failIf(True)
1764
1765
1766 ##############
1767 # CASE 950 #
1768 ##############
1769 def test_950(self):
1770 self.case_no = self.get_case_number()
1771 self.log.info(' CASE %s log: ' % str(self.case_no))
1772 self.driver.maximize_window()
1773 self.driver.get(self.base_url)
1774 # step3&4: so far we're not sure if there's "successful build" or "failed
1775 # build".If either of them doesn't exist, we can still go on other steps
1776 check_list = ['Configuration', 'Tasks', 'Recipes', 'Packages', 'Time', 'CPU usage', 'Disk I/O']
1777 has_successful_build = 1
1778 has_failed_build = 1
1779 try:
1780 pass_icon = self.driver.find_element_by_xpath("//*[@class='icon-ok-sign success']")
1781 except Exception:
1782 self.log.info("no successful build exists")
1783 has_successful_build = 0
1784 pass
1785 if has_successful_build:
1786 pass_icon.click()
1787 # save screen here to check if it matches requirement.
1788 self.browser_delay()
1789 self.save_screenshot(screenshot_type='selenium', append_name='step3_1')
1790 for item in check_list:
1791 try:
1792 self.find_element_by_link_text_in_table('nav', item)
1793 except Exception:
1794 self.log.error("link %s cannot be found in the page" % item)
1795 self.failIf(True)
1796 # step 6
1797 check_list_2 = ['Packages included', 'Total package size', \
1798 'License manifest', 'Image files']
1799 self.failUnless(self.is_text_present(check_list_2))
1800 self.driver.back()
1801 try:
1802 fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']")
1803 except Exception:
1804 has_failed_build = 0
1805 self.log.info("no failed build exists")
1806 pass
1807 if has_failed_build:
1808 fail_icon.click()
1809 # save screen here to check if it matches requirement.
1810 self.browser_delay()
1811 self.save_screenshot(screenshot_type='selenium', append_name='step3_2')
1812 for item in check_list:
1813 try:
1814 self.find_element_by_link_text_in_table('nav', item)
1815 except Exception:
1816 self.log.error("link %s cannot be found in the page" % item)
1817 self.failIf(True)
1818 # step 7 involved
1819 check_list_3 = ['Machine', 'Distro', 'Layers', 'Total number of tasks', 'Tasks executed', \
1820 'Tasks not executed', 'Reuse', 'Recipes built', 'Packages built']
1821 self.failUnless(self.is_text_present(check_list_3))
1822 self.driver.back()
1823
1824
1825 ##############
1826 # CASE 951 #
1827 ##############
1828 def test_951(self):
1829 self.case_no = self.get_case_number()
1830 self.log.info(' CASE %s log: ' % str(self.case_no))
1831 self.driver.maximize_window()
1832 self.driver.get(self.base_url)
1833 # currently test case itself isn't responsible for creating "1 successful and
1834 # 1 failed build"
1835 has_successful_build = 1
1836 has_failed_build = 1
1837 try:
1838 fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']")
1839 except Exception:
1840 has_failed_build = 0
1841 self.log.info("no failed build exists")
1842 pass
1843 # if there's failed build, we can proceed
1844 if has_failed_build:
1845 self.driver.find_element_by_partial_link_text("error").click()
1846 self.driver.back()
1847 # not sure if there "must be" some warnings, so here save a screen
1848 self.browser_delay()
1849 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1850
1851
1852 ##############
1853 # CASE 955 #
1854 ##############
1855 def test_955(self):
1856 self.case_no = self.get_case_number()
1857 self.log.info(' CASE %s log: ' % str(self.case_no))
1858 self.driver.maximize_window()
1859 self.driver.get(self.base_url)
1860 self.log.info(" You should manually create all images before test starts!")
1861 # So far the case itself is not responsable for creating all sorts of images.
1862 # So assuming they are already there
1863 # step 2
1864 self.driver.find_element_by_link_text("core-image-minimal").click()
1865 # save screen here to see the page component
1866
1867
1868 ##############
1869 # CASE 956 #
1870 ##############
1871 def test_956(self):
1872 self.case_no = self.get_case_number()
1873 self.log.info(' CASE %s log: ' % str(self.case_no))
1874 self.driver.maximize_window()
1875 self.driver.get(self.base_url)
1876 # step 2-3 need to run manually
1877 self.log.info("step 2-3: checking the help message when you hover on help icon of target,\
1878 tasks, recipes, packages need to run manually")
1879 self.driver.find_element_by_partial_link_text("Toaster manual").click()
1880 if not self.is_text_present("Toaster Manual"):
1881 self.log.error("please check [Toaster manual] link on page")
1882 self.failIf(True)
1883