blob: d8f838aeaff0ed1a2ac7f37ba67cbb51ddf38eef [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
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050026import shutil, argparse, ConfigParser, platform, json
Patrick Williamsc124f4f2015-09-15 14:41:29 -050027from 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
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050033import sqlite3 as sqlite
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034
35
36###########################################
37# #
38# PART I: utils stuff #
39# #
40###########################################
41
42class Listattr(object):
43 """
44 Set of list attribute. This is used to determine what the list content is.
45 Later on we may add more attributes here.
46 """
47 NULL = "null"
48 NUMBERS = "numbers"
49 STRINGS = "strings"
50 PERCENT = "percentage"
51 SIZE = "size"
52 UNKNOWN = "unknown"
53
54
55def get_log_root_dir():
56 max_depth = 5
57 parent_dir = '../'
58 for number in range(0, max_depth):
59 if os.path.isdir(sys.path[0] + os.sep + (os.pardir + os.sep)*number + 'log'):
60 log_root_dir = os.path.abspath(sys.path[0] + os.sep + (os.pardir + os.sep)*number + 'log')
61 break
62
63 if number == (max_depth - 1):
64 print 'No log dir found. Please check'
65 raise Exception
66
67 return log_root_dir
68
69
70def mkdir_p(dir):
71 try:
72 os.makedirs(dir)
73 except OSError as exc:
74 if exc.errno == errno.EEXIST and os.path.isdir(dir):
75 pass
76 else:
77 raise
78
79
80def get_list_attr(testlist):
81 """
82 To determine the list content
83 """
84 if not testlist:
85 return Listattr.NULL
86 listtest = testlist[:]
87 try:
88 listtest.remove('')
89 except ValueError:
90 pass
91 pattern_percent = re.compile(r"^([0-9])+(\.)?([0-9])*%$")
92 pattern_size = re.compile(r"^([0-9])+(\.)?([0-9])*( )*(K)*(M)*(G)*B$")
93 pattern_number = re.compile(r"^([0-9])+(\.)?([0-9])*$")
94 def get_patterned_number(pattern, tlist):
95 count = 0
96 for item in tlist:
97 if re.search(pattern, item):
98 count += 1
99 return count
100 if get_patterned_number(pattern_percent, listtest) == len(listtest):
101 return Listattr.PERCENT
102 elif get_patterned_number(pattern_size, listtest) == len(listtest):
103 return Listattr.SIZE
104 elif get_patterned_number(pattern_number, listtest) == len(listtest):
105 return Listattr.NUMBERS
106 else:
107 return Listattr.STRINGS
108
109
110def is_list_sequenced(testlist):
111 """
112 Function to tell if list is sequenced
113 Currently we may have list made up of: Strings ; numbers ; percentage ; time; size
114 Each has respective way to determine if it's sequenced.
115 """
116 test_list = testlist[:]
117 try:
118 test_list.remove('')
119 except ValueError:
120 pass
121
122 if get_list_attr(testlist) == Listattr.NULL :
123 return True
124
125 elif get_list_attr(testlist) == Listattr.STRINGS :
126 return (sorted(test_list) == test_list)
127
128 elif get_list_attr(testlist) == Listattr.NUMBERS :
129 list_number = []
130 for item in test_list:
131 list_number.append(eval(item))
132 return (sorted(list_number) == list_number)
133
134 elif get_list_attr(testlist) == Listattr.PERCENT :
135 list_number = []
136 for item in test_list:
137 list_number.append(eval(item.strip('%')))
138 return (sorted(list_number) == list_number)
139
140 elif get_list_attr(testlist) == Listattr.SIZE :
141 list_number = []
142 # currently SIZE is splitted by space
143 for item in test_list:
144 if item.split()[1].upper() == "KB":
145 list_number.append(1024 * eval(item.split()[0]))
146 elif item.split()[1].upper() == "MB":
147 list_number.append(1024 * 1024 * eval(item.split()[0]))
148 elif item.split()[1].upper() == "GB":
149 list_number.append(1024 * 1024 * 1024 * eval(item.split()[0]))
150 else:
151 list_number.append(eval(item.split()[0]))
152 return (sorted(list_number) == list_number)
153
154 else:
155 print 'Unrecognized list type, please check'
156 return False
157
158
159def is_list_inverted(testlist):
160 """
161 Function to tell if list is inverted
162 Currently we may have list made up of: Strings ; numbers ; percentage ; time; size
163 Each has respective way to determine if it's inverted.
164 """
165 test_list = testlist[:]
166 try:
167 test_list.remove('')
168 except ValueError:
169 pass
170
171 if get_list_attr(testlist) == Listattr.NULL :
172 return True
173
174 elif get_list_attr(testlist) == Listattr.STRINGS :
175 return (sorted(test_list, reverse = True) == test_list)
176
177 elif get_list_attr(testlist) == Listattr.NUMBERS :
178 list_number = []
179 for item in test_list:
180 list_number.append(eval(item))
181 return (sorted(list_number, reverse = True) == list_number)
182
183 elif get_list_attr(testlist) == Listattr.PERCENT :
184 list_number = []
185 for item in test_list:
186 list_number.append(eval(item.strip('%')))
187 return (sorted(list_number, reverse = True) == list_number)
188
189 elif get_list_attr(testlist) == Listattr.SIZE :
190 list_number = []
191 # currently SIZE is splitted by space. such as 0 B; 1 KB; 2 MB
192 for item in test_list:
193 if item.split()[1].upper() == "KB":
194 list_number.append(1024 * eval(item.split()[0]))
195 elif item.split()[1].upper() == "MB":
196 list_number.append(1024 * 1024 * eval(item.split()[0]))
197 elif item.split()[1].upper() == "GB":
198 list_number.append(1024 * 1024 * 1024 * eval(item.split()[0]))
199 else:
200 list_number.append(eval(item.split()[0]))
201 return (sorted(list_number, reverse = True) == list_number)
202
203 else:
204 print 'Unrecognized list type, please check'
205 return False
206
207def replace_file_content(filename, item, option):
208 f = open(filename)
209 lines = f.readlines()
210 f.close()
211 output = open(filename, 'w')
212 for line in lines:
213 if line.startswith(item):
214 output.write(item + " = '" + option + "'\n")
215 else:
216 output.write(line)
217 output.close()
218
219def extract_number_from_string(s):
220 """
221 extract the numbers in a string. return type is 'list'
222 """
223 return re.findall(r'([0-9]+)', s)
224
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500225# Below is decorator derived from toaster backend test code
226class NoParsingFilter(logging.Filter):
227 def filter(self, record):
228 return record.levelno == 100
229
230def LogResults(original_class):
231 orig_method = original_class.run
232
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500233 from time import strftime, gmtime
234 caller = 'toaster'
235 timestamp = strftime('%Y%m%d%H%M%S',gmtime())
236 logfile = os.path.join(os.getcwd(),'results-'+caller+'.'+timestamp+'.log')
237 linkfile = os.path.join(os.getcwd(),'results-'+caller+'.log')
238
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500239 #rewrite the run method of unittest.TestCase to add testcase logging
240 def run(self, result, *args, **kws):
241 orig_method(self, result, *args, **kws)
242 passed = True
243 testMethod = getattr(self, self._testMethodName)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500244 #if test case is decorated then use it's number, else use it's name
245 try:
246 test_case = testMethod.test_case
247 except AttributeError:
248 test_case = self._testMethodName
249
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500250 class_name = str(testMethod.im_class).split("'")[1]
251
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500252 #create custom logging level for filtering.
253 custom_log_level = 100
254 logging.addLevelName(custom_log_level, 'RESULTS')
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500255
256 def results(self, message, *args, **kws):
257 if self.isEnabledFor(custom_log_level):
258 self.log(custom_log_level, message, *args, **kws)
259 logging.Logger.results = results
260
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500261 logging.basicConfig(filename=logfile,
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500262 filemode='w',
263 format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
264 datefmt='%H:%M:%S',
265 level=custom_log_level)
266 for handler in logging.root.handlers:
267 handler.addFilter(NoParsingFilter())
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500268 local_log = logging.getLogger(caller)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500269
270 #check status of tests and record it
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500271
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500272 for (name, msg) in result.errors:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500273 if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500274 local_log.results("Testcase "+str(test_case)+": ERROR")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500275 local_log.results("Testcase "+str(test_case)+":\n"+msg)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500276 passed = False
277 for (name, msg) in result.failures:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500278 if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500279 local_log.results("Testcase "+str(test_case)+": FAILED")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500280 local_log.results("Testcase "+str(test_case)+":\n"+msg)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500281 passed = False
282 for (name, msg) in result.skipped:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500283 if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
284 local_log.results("Testcase "+str(test_case)+": SKIPPED")
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500285 passed = False
286 if passed:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500287 local_log.results("Testcase "+str(test_case)+": PASSED")
288
289 # Create symlink to the current log
290 if os.path.exists(linkfile):
291 os.remove(linkfile)
292 os.symlink(logfile, linkfile)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500293
294 original_class.run = run
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500295
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500296 return original_class
297
298
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500299###########################################
300# #
301# PART II: base class #
302# #
303###########################################
304
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500305@LogResults
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500306class toaster_cases_base(unittest.TestCase):
307
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500308 @classmethod
309 def setUpClass(cls):
310 cls.log = cls.logger_create()
311
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500312 def setUp(self):
313 self.screenshot_sequence = 1
314 self.verificationErrors = []
315 self.accept_next_alert = True
316 self.host_os = platform.system().lower()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500317 if os.getenv('TOASTER_SUITE'):
318 self.target_suite = os.getenv('TOASTER_SUITE')
319 else:
320 self.target_suite = self.host_os
321
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500322 self.parser = ConfigParser.SafeConfigParser()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500323 self.parser.read('toaster_test.cfg')
324 self.base_url = eval(self.parser.get('toaster_test_' + self.target_suite, 'toaster_url'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500325
326 # create log dir . Currently , we put log files in log/tmp. After all
327 # test cases are done, move them to log/$datetime dir
328 self.log_tmp_dir = os.path.abspath(sys.path[0]) + os.sep + 'log' + os.sep + 'tmp'
329 try:
330 mkdir_p(self.log_tmp_dir)
331 except OSError :
332 logging.error("%(asctime)s Cannot create tmp dir under log, please check your privilege")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500333 # self.log = self.logger_create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500334 # driver setup
335 self.setup_browser()
336
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500337 @staticmethod
338 def logger_create():
339 log_file = "toaster-auto-" + time.strftime("%Y%m%d%H%M%S") + ".log"
340 if os.path.exists("toaster-auto.log"): os.remove("toaster-auto.log")
341 os.symlink(log_file, "toaster-auto.log")
342
343 log = logging.getLogger("toaster")
344 log.setLevel(logging.DEBUG)
345
346 fh = logging.FileHandler(filename=log_file, mode='w')
347 fh.setLevel(logging.DEBUG)
348
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500349 ch = logging.StreamHandler(sys.stdout)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500350 ch.setLevel(logging.INFO)
351
352 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500353 fh.setFormatter(formatter)
354 ch.setFormatter(formatter)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500355
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356 log.addHandler(fh)
357 log.addHandler(ch)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500358
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500359 return log
360
361
362 def setup_browser(self, *browser_path):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500363 self.browser = eval(self.parser.get('toaster_test_' + self.target_suite, 'test_browser'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500364 print self.browser
365 if self.browser == "firefox":
366 driver = webdriver.Firefox()
367 elif self.browser == "chrome":
368 driver = webdriver.Chrome()
369 elif self.browser == "ie":
370 driver = webdriver.Ie()
371 else:
372 driver = None
373 print "unrecognized browser type, please check"
374 self.driver = driver
375 self.driver.implicitly_wait(30)
376 return self.driver
377
378
379 def save_screenshot(self, **log_args):
380 """
381 This function is used to save screen either by os interface or selenium interface.
382 How to use:
383 self.save_screenshot(screenshot_type = 'native'/'selenium', log_sub_dir = 'xxx',
384 append_name = 'stepx')
385 where native means screenshot func provided by OS,
386 selenium means screenshot func provided by selenium webdriver
387 """
388 types = [log_args.get('screenshot_type')]
389 # when no screenshot_type is specified
390 if types == [None]:
391 types = ['native', 'selenium']
392 # normally append_name is used to specify which step..
393 add_name = log_args.get('append_name')
394 if not add_name:
395 add_name = '-'
396 # normally there's no need to specify sub_dir
397 sub_dir = log_args.get('log_sub_dir')
398 if not sub_dir:
399 # use casexxx as sub_dir name
400 sub_dir = 'case' + str(self.case_no)
401 for item in types:
402 log_dir = self.log_tmp_dir + os.sep + sub_dir
403 mkdir_p(log_dir)
404 log_path = log_dir + os.sep + self.browser + '-' +\
405 item + '-' + add_name + '-' + str(self.screenshot_sequence) + '.png'
406 if item == 'native':
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500407 if self.host_os == "linux":
408 os.system("scrot " + log_path)
409 elif self.host_os=="darwin":
410 os.system("screencapture -x " + log_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411 elif item == 'selenium':
412 self.driver.get_screenshot_as_file(log_path)
413 self.screenshot_sequence += 1
414
415 def browser_delay(self):
416 """
417 currently this is a workaround for some chrome test.
418 Sometimes we need a delay to accomplish some operation.
419 But for firefox, mostly we don't need this.
420 To be discussed
421 """
422 if self.browser == "chrome":
423 time.sleep(1)
424 return
425
426
427# these functions are not contained in WebDriver class..
428 def find_element_by_text(self, string):
429 return self.driver.find_element_by_xpath("//*[text()='" + string + "']")
430
431
432 def find_elements_by_text(self, string):
433 return self.driver.find_elements_by_xpath("//*[text()='" + string + "']")
434
435
436 def find_element_by_text_in_table(self, table_id, text_string):
437 """
438 This is used to search some certain 'text' in certain table
439 """
440 try:
441 table_element = self.get_table_element(table_id)
442 element = table_element.find_element_by_xpath("//*[text()='" + text_string + "']")
443 except NoSuchElementException, e:
444 print 'no element found'
445 raise
446 return element
447
448
449 def find_element_by_link_text_in_table(self, table_id, link_text):
450 """
451 Assume there're multiple suitable "find_element_by_link_text".
452 In this circumstance we need to specify "table".
453 """
454 try:
455 table_element = self.get_table_element(table_id)
456 element = table_element.find_element_by_link_text(link_text)
457 except NoSuchElementException, e:
458 print 'no element found'
459 raise
460 return element
461
462
463 def find_elements_by_link_text_in_table(self, table_id, link_text):
464 """
465 Search link-text in certain table. This helps to narrow down search area.
466 """
467 try:
468 table_element = self.get_table_element(table_id)
469 element_list = table_element.find_elements_by_link_text(link_text)
470 except NoSuchElementException, e:
471 print 'no element found'
472 raise
473 return element_list
474
475
476 def find_element_by_partial_link_text_in_table(self, table_id, link_text):
477 """
478 Search element by partial link text in certain table.
479 """
480 try:
481 table_element = self.get_table_element(table_id)
482 element = table_element.find_element_by_partial_link_text(link_text)
483 return element
484 except NoSuchElementException, e:
485 print 'no element found'
486 raise
487
488
489 def find_elements_by_partial_link_text_in_table(self, table_id, link_text):
490 """
491 Assume there're multiple suitable "find_partial_element_by_link_text".
492 """
493 try:
494 table_element = self.get_table_element(table_id)
495 element_list = table_element.find_elements_by_partial_link_text(link_text)
496 return element_list
497 except NoSuchElementException, e:
498 print 'no element found'
499 raise
500
501
502 def find_element_by_xpath_in_table(self, table_id, xpath):
503 """
504 This helps to narrow down search area. Especially useful when dealing with pop-up form.
505 """
506 try:
507 table_element = self.get_table_element(table_id)
508 element = table_element.find_element_by_xpath(xpath)
509 except NoSuchElementException, e:
510 print 'no element found'
511 raise
512 return element
513
514
515 def find_elements_by_xpath_in_table(self, table_id, xpath):
516 """
517 This helps to narrow down search area. Especially useful when dealing with pop-up form.
518 """
519 try:
520 table_element = self.get_table_element(table_id)
521 element_list = table_element.find_elements_by_xpath(xpath)
522 except NoSuchElementException, e:
523 print 'no elements found'
524 raise
525 return element_list
526
527
528 def shortest_xpath(self, pname, pvalue):
529 return "//*[@" + pname + "='" + pvalue + "']"
530
531
532#usually elements in the same column are with same class name. for instance: class="outcome" .TBD
533 def get_table_column_text(self, attr_name, attr_value):
534 c_xpath = self.shortest_xpath(attr_name, attr_value)
535 elements = self.driver.find_elements_by_xpath(c_xpath)
536 c_list = []
537 for element in elements:
538 c_list.append(element.text)
539 return c_list
540
541
542 def get_table_column_text_by_column_number(self, table_id, column_number):
543 c_xpath = "//*[@id='" + table_id + "']//td[" + str(column_number) + "]"
544 elements = self.driver.find_elements_by_xpath(c_xpath)
545 c_list = []
546 for element in elements:
547 c_list.append(element.text)
548 return c_list
549
550
551 def get_table_head_text(self, *table_id):
552#now table_id is a tuple...
553 if table_id:
554 thead_xpath = "//*[@id='" + table_id[0] + "']//thead//th[text()]"
555 elements = self.driver.find_elements_by_xpath(thead_xpath)
556 c_list = []
557 for element in elements:
558 if element.text:
559 c_list.append(element.text)
560 return c_list
561#default table on page
562 else:
563 return self.driver.find_element_by_xpath("//*/table/thead").text
564
565
566
567 def get_table_element(self, table_id, *coordinate):
568 if len(coordinate) == 0:
569#return whole-table element
570 element_xpath = "//*[@id='" + table_id + "']"
571 try:
572 element = self.driver.find_element_by_xpath(element_xpath)
573 except NoSuchElementException, e:
574 raise
575 return element
576 row = coordinate[0]
577
578 if len(coordinate) == 1:
579#return whole-row element
580 element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]"
581 try:
582 element = self.driver.find_element_by_xpath(element_xpath)
583 except NoSuchElementException, e:
584 return False
585 return element
586#now we are looking for an element with specified X and Y
587 column = coordinate[1]
588
589 element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]/td[" + str(column) + "]"
590 try:
591 element = self.driver.find_element_by_xpath(element_xpath)
592 except NoSuchElementException, e:
593 return False
594 return element
595
596
597 def get_table_data(self, table_id, row_count, column_count):
598 row = 1
599 Lists = []
600 while row <= row_count:
601 column = 1
602 row_content=[]
603 while column <= column_count:
604 s= "//*[@id='" + table_id + "']/tbody/tr[" + str(row) +"]/td[" + str(column) + "]"
605 v = self.driver.find_element_by_xpath(s).text
606 row_content.append(v)
607 column = column + 1
608 print("row_content=",row_content)
609 Lists.extend(row_content)
610 print Lists[row-1][0]
611 row = row + 1
612 return Lists
613
614 # The is_xxx_present functions only returns True/False
615 # All the log work is done in test procedure, so we can easily trace back
616 # using logging
617 def is_text_present (self, patterns):
618 for pattern in patterns:
619 if str(pattern) not in self.driver.page_source:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500620 print 'Text "'+pattern+'" is missing'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500621 return False
622 return True
623
624
625 def is_element_present(self, how, what):
626 try:
627 self.driver.find_element(how, what)
628 except NoSuchElementException, e:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500629 print 'Could not find element '+str(what)+' by ' + str(how)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500630 return False
631 return True
632
633
634 def is_alert_present(self):
635 try: self.driver.switch_to_alert()
636 except NoAlertPresentException, e: return False
637 return True
638
639
640 def close_alert_and_get_its_text(self):
641 try:
642 alert = self.driver.switch_to_alert()
643 alert_text = alert.text
644 if self.accept_next_alert:
645 alert.accept()
646 else:
647 alert.dismiss()
648 return alert_text
649 finally: self.accept_next_alert = True
650
651
652 def get_case_number(self):
653 """
654 what case are we running now
655 """
656 funcname = sys._getframe(1).f_code.co_name
657 caseno_str = funcname.strip('test_')
658 try:
659 caseno = int(caseno_str)
660 except ValueError:
661 print "get case number error! please check if func name is test_xxx"
662 return False
663 return caseno
664
665
666 def tearDown(self):
667 self.log.info(' END: CASE %s log \n\n' % str(self.case_no))
668 self.driver.quit()
669 self.assertEqual([], self.verificationErrors)
670
671
672###################################################################
673# #
674# PART III: test cases #
675# please refer to #
676# https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=xxx #
677# #
678###################################################################
679
680# Note: to comply with the unittest framework, we call these test_xxx functions
681# from run_toastercases.py to avoid calling setUp() and tearDown() multiple times
682
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500683
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500684class toaster_cases(toaster_cases_base):
685 ##############
686 # CASE 901 #
687 ##############
688 def test_901(self):
689 # the reason why get_case_number is not in setUp function is that
690 # otherwise it returns "setUp" instead of "test_xxx"
691 self.case_no = self.get_case_number()
692 self.log.info(' CASE %s log: ' % str(self.case_no))
693 self.driver.maximize_window()
694 self.driver.get(self.base_url)
695 # open all columns
696 self.driver.find_element_by_id("edit-columns-button").click()
697 # adding explicitly wait for chromedriver..-_-
698 self.browser_delay()
699 self.driver.find_element_by_id("started_on").click()
700 self.browser_delay()
701 self.driver.find_element_by_id("time").click()
702 self.driver.find_element_by_id("edit-columns-button").click()
703 # dict: {lint text name : actual class name}
704 table_head_dict = {'Outcome':'outcome', 'Recipe':'target', 'Machine':'machine', 'Started on':'started_on', 'Completed on':'completed_on', \
705 'Errors':'errors_no', 'Warnings':'warnings_no', 'Time':'time'}
706 for key in table_head_dict:
707 try:
708 self.driver.find_element_by_link_text(key).click()
709 except Exception, e:
710 self.log.error("%s cannot be found on page" % key)
711 raise
712 column_list = self.get_table_column_text("class", table_head_dict[key])
713 # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
714 # the point is, after another click, it should be another order
715 if is_list_inverted(column_list):
716 self.driver.find_element_by_link_text(key).click()
717 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500718 self.assertTrue(is_list_sequenced(column_list), msg=("%s column not in order" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500719 else:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500720 self.assertTrue(is_list_sequenced(column_list), msg=("%s column not sequenced" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721 self.driver.find_element_by_link_text(key).click()
722 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500723 self.assertTrue(is_list_inverted(column_list), msg=("%s column not inverted" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500724 self.log.info("case passed")
725
726
727 ##############
728 # CASE 902 #
729 ##############
730 def test_902(self):
731 self.case_no = self.get_case_number()
732 self.log.info(' CASE %s log: ' % str(self.case_no))
733 self.driver.maximize_window()
734 self.driver.get(self.base_url)
735 # Could add more test patterns here in the future. Also, could search some items other than target column in future..
736 patterns = ["minimal", "sato"]
737 for pattern in patterns:
738 ori_target_column_texts = self.get_table_column_text("class", "target")
739 print ori_target_column_texts
740 self.driver.find_element_by_id("search").clear()
741 self.driver.find_element_by_id("search").send_keys(pattern)
742 self.driver.find_element_by_id("search-button").click()
743 new_target_column_texts = self.get_table_column_text("class", "target")
744 # if nothing found, we still count it as "pass"
745 if new_target_column_texts:
746 for text in new_target_column_texts:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500747 self.assertTrue(text.find(pattern), msg=("%s item doesn't exist " % pattern))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500748 self.driver.find_element_by_css_selector("i.icon-remove").click()
749 target_column_texts = self.get_table_column_text("class", "target")
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500750 self.assertTrue(ori_target_column_texts == target_column_texts, msg=("builds changed after operations"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500751
752
753 ##############
754 # CASE 903 #
755 ##############
756 def test_903(self):
757 self.case_no = self.get_case_number()
758 self.log.info(' CASE %s log: ' % str(self.case_no))
759 self.driver.maximize_window()
760 self.driver.get(self.base_url)
761 # when opening a new page, "started_on" is not displayed by default
762 self.driver.find_element_by_id("edit-columns-button").click()
763 # currently all the delay are for chrome driver -_-
764 self.browser_delay()
765 self.driver.find_element_by_id("started_on").click()
766 self.driver.find_element_by_id("edit-columns-button").click()
767 # step 4
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500768 items = ["Outcome", "Completed on", "Started on"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500769 for item in items:
770 try:
771 temp_element = self.find_element_by_text_in_table('otable', item)
772 # this is how we find "filter icon" in the same level as temp_element(where "a" means clickable, "i" means icon)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500773 self.assertTrue(temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500774 except Exception,e:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500775 self.assertFalse(True, msg=(" %s cannot be found! %s" % (item, e)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500776 raise
777 # step 5-6
778 temp_element = self.find_element_by_link_text_in_table('otable', 'Outcome')
779 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
780 self.browser_delay()
781 # the 2nd option, whatever it is
782 self.driver.find_element_by_xpath("(//input[@name='filter'])[2]").click()
783 # click "Apply" button
784 self.driver.find_element_by_xpath("//*[@id='filter_outcome']//*[text()='Apply']").click()
785 # save screen here
786 time.sleep(1)
787 self.save_screenshot(screenshot_type='selenium', append_name='step5')
788 temp_element = self.find_element_by_link_text_in_table('otable', 'Completed on')
789 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
790 self.browser_delay()
791 self.driver.find_element_by_xpath("//*[@id='filter_completed_on']//*[text()='Apply']").click()
792 # save screen here to compare to previous one
793 # please note that for chrome driver, need a little break before saving
794 # screen here -_-
795 self.browser_delay()
796 self.save_screenshot(screenshot_type='selenium', append_name='step6')
797 self.driver.find_element_by_id("search").clear()
798 self.driver.find_element_by_id("search").send_keys("core-image")
799 self.driver.find_element_by_id("search-button").click()
800
801
802 ##############
803 # CASE 904 #
804 ##############
805 def test_904(self):
806 self.case_no = self.get_case_number()
807 self.log.info(' CASE %s log: ' % str(self.case_no))
808 self.driver.maximize_window()
809 self.driver.get(self.base_url)
810 self.driver.find_element_by_partial_link_text("core-image").click()
811 self.driver.find_element_by_link_text("Tasks").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500812 self.table_name = 'otable'
813 # This is how we find the "default" rows-number!
814 rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text)
815 print rows_displayed
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500816 self.assertTrue(self.get_table_element(self.table_name, rows_displayed), msg=("not enough rows displayed"))
817 self.assertFalse(self.get_table_element(self.table_name, rows_displayed + 1), \
818 msg=("more rows displayed than expected"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500819 # Search text box background text is "Search tasks"
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500820 self.assertTrue(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search tasks']"),\
821 msg=("background text doesn't exist"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500822
823 self.driver.find_element_by_id("search").clear()
824 self.driver.find_element_by_id("search").send_keys("busybox")
825 self.driver.find_element_by_id("search-button").click()
826 self.browser_delay()
827 self.save_screenshot(screenshot_type='selenium', append_name='step5')
828 self.driver.find_element_by_css_selector("i.icon-remove").click()
829 # Save screen here
830 self.save_screenshot(screenshot_type='selenium', append_name='step5_2')
831 self.driver.find_element_by_id("edit-columns-button").click()
832 self.driver.find_element_by_id("cpu_used").click()
833 self.driver.find_element_by_id("disk_io").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500834 self.driver.find_element_by_id("recipe_version").click()
835 self.driver.find_element_by_id("time_taken").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500836 self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500837 # The operation is the same as case901
838 # dict: {lint text name : actual class name}
839 table_head_dict = {'Order':'order', 'Recipe':'recipe_name', 'Task':'task_name', 'Executed':'executed', \
840 'Outcome':'outcome', 'Cache attempt':'cache_attempt', 'Time (secs)':'time_taken', 'CPU usage':'cpu_used', \
841 'Disk I/O (ms)':'disk_io'}
842 for key in table_head_dict:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500843 # This is tricky here: we are doing so because there may be more than 1
844 # same-name link_text in one page. So we only find element inside the table
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500845 self.find_element_by_link_text_in_table(self.table_name, key).click()
846 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500847 # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
848 # the point is, after another click, it should be another order
849 # the first case is special:this means every item in column_list is the same, so
850 # after one click, either sequenced or inverted will be fine
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500851 if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \
852 or (not column_list) :
853 self.find_element_by_link_text_in_table(self.table_name, key).click()
854 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500855 self.assertTrue(is_list_sequenced(column_list) or is_list_inverted(column_list), \
856 msg=("%s column not in any order" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500857 elif is_list_inverted(column_list):
858 self.find_element_by_link_text_in_table(self.table_name, key).click()
859 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500860 self.assertTrue(is_list_sequenced(column_list), msg=("%s column not in order" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500861 else:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500862 self.assertTrue(is_list_sequenced(column_list), msg=("%s column not in order" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500863 self.find_element_by_link_text_in_table(self.table_name, key).click()
864 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500865 self.assertTrue(is_list_inverted(column_list), msg=("%s column not inverted" % key))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500866 # step 8-10
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500867 # filter dict: {link text name : filter table name in xpath}
868 filter_dict = {'Executed':'filter_executed', 'Outcome':'filter_outcome', 'Cache attempt':'filter_cache_attempt'}
869 for key in filter_dict:
870 temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
871 # find the filter icon besides it.
872 # And here we must have break (1 sec) to get the popup stuff
873 temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
874 self.browser_delay()
875 avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
876 for number in range(0, len(avail_options)):
877 avail_options[number].click()
878 self.browser_delay()
879 # click "Apply"
880 self.driver.find_element_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@type='submit']").click()
881 # insert screen capture here
882 self.browser_delay()
883 self.save_screenshot(screenshot_type='selenium', append_name='step8')
884 # after the last option was clicked, we don't need operation below anymore
885 if number < len(avail_options)-1:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500886 try:
887 temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
888 temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
889 avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
890 except:
891 print "in exception"
892 self.find_element_by_text("Show all tasks").click()
893# self.driver.find_element_by_xpath("//*[@id='searchform']/button[2]").click()
894 temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
895 temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
896 avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500897 self.browser_delay()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500898 # step 11
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500899 for item in ['order', 'task_name', 'executed', 'outcome', 'recipe_name', 'recipe_version']:
900 try:
901 self.find_element_by_xpath_in_table(self.table_name, "./tbody/tr[1]/*[@class='" + item + "']/a").click()
902 except NoSuchElementException, e:
903 # let it go...
904 print 'no item in the colum' + item
905 # insert screen shot here
906 self.save_screenshot(screenshot_type='selenium', append_name='step11')
907 self.driver.back()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500908 # step 12-14
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500909 # about test_dict: please refer to testcase 904 requirement step 12-14
910 test_dict = {
911 'Time':{
912 'class':'time_taken',
913 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Time (secs)'],
914 'check_column_list':['cpu_used', 'cache_attempt', 'disk_io', 'order', 'recipe_version']
915 },
916 'CPU usage':{
917 'class':'cpu_used',
918 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'CPU usage'],
919 'check_column_list':['cache_attempt', 'disk_io', 'order', 'recipe_version', 'time_taken']
920 },
921 'Disk I/O':{
922 'class':'disk_io',
923 'check_head_list':['Recipe', 'Task', 'Executed', 'Outcome', 'Disk I/O (ms)'],
924 'check_column_list':['cpu_used', 'cache_attempt', 'order', 'recipe_version', 'time_taken']
925 }
926 }
927 for key in test_dict:
928 self.find_element_by_partial_link_text_in_table('nav', 'core-image').click()
929 self.find_element_by_link_text_in_table('nav', key).click()
930 head_list = self.get_table_head_text('otable')
931 for item in test_dict[key]['check_head_list']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500932 self.assertTrue(item in head_list, msg=("%s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500933 column_list = self.get_table_column_text('class', test_dict[key]['class'])
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500934 self.assertTrue(is_list_inverted(column_list), msg=("%s column not inverted" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500935
936 self.driver.find_element_by_id("edit-columns-button").click()
937 for item2 in test_dict[key]['check_column_list']:
938 self.driver.find_element_by_id(item2).click()
939 self.driver.find_element_by_id("edit-columns-button").click()
940 # TBD: save screen here
941
942
943 ##############
944 # CASE 906 #
945 ##############
946 def test_906(self):
947 self.case_no = self.get_case_number()
948 self.log.info(' CASE %s log: ' % str(self.case_no))
949 self.driver.maximize_window()
950 self.driver.get(self.base_url)
951 self.driver.find_element_by_link_text("core-image-minimal").click()
952 self.find_element_by_link_text_in_table('nav', 'Packages').click()
953 # find "bash" in first column (Packages)
954 self.driver.find_element_by_xpath("//*[@id='otable']//td[1]//*[text()='bash']").click()
955 # save sceen here to observe...
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500956 # step 6
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500957 self.driver.find_element_by_partial_link_text("Generated files").click()
958 head_list = self.get_table_head_text('otable')
959 for item in ['File', 'Size']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500960 self.assertTrue(item in head_list, msg=("%s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500961 c_list = self.get_table_column_text('class', 'path')
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500962 self.assertTrue(is_list_sequenced(c_list), msg=("column not in order"))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500963 # step 7
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500964 self.driver.find_element_by_partial_link_text("Runtime dependencies").click()
965 # save sceen here to observe...
966 # note that here table name is not 'otable'
967 head_list = self.get_table_head_text('dependencies')
968 for item in ['Package', 'Version', 'Size']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500969 self.assertTrue(item in head_list, msg=("%s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500970 c_list = self.get_table_column_text_by_column_number('dependencies', 1)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500971 self.assertTrue(is_list_sequenced(c_list), msg=("list not in order"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500972 texts = ['Size', 'License', 'Recipe', 'Recipe version', 'Layer', \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500973 'Layer commit']
974 self.failUnless(self.is_text_present(texts))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500975
976
977 ##############
978 # CASE 910 #
979 ##############
980 def test_910(self):
981 self.case_no = self.get_case_number()
982 self.log.info(' CASE %s log: ' % str(self.case_no))
983 image_type="core-image-minimal"
984 test_package1="busybox"
985 test_package2="lib"
986 self.driver.maximize_window()
987 self.driver.get(self.base_url)
988 self.driver.find_element_by_link_text(image_type).click()
989 self.driver.find_element_by_link_text("Recipes").click()
990 self.save_screenshot(screenshot_type='selenium', append_name='step3')
991
992 self.table_name = 'otable'
993 # This is how we find the "default" rows-number!
994 rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text)
995 print rows_displayed
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500996 self.assertTrue(self.get_table_element(self.table_name, rows_displayed))
997 self.assertFalse(self.get_table_element(self.table_name, rows_displayed + 1))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500998
999 # Check the default table is sorted by Recipe
1000 tasks_column_count = len(self.driver.find_elements_by_xpath("/html/body/div[2]/div/div[2]/div[2]/table/tbody/tr/td[1]"))
1001 print tasks_column_count
1002 default_column_list = self.get_table_column_text_by_column_number(self.table_name, 1)
1003 #print default_column_list
1004
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001005 self.assertTrue(is_list_sequenced(default_column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001006
1007 # Search text box background text is "Search recipes"
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001008 self.assertTrue(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001009
1010 self.driver.find_element_by_id("search").clear()
1011 self.driver.find_element_by_id("search").send_keys(test_package1)
1012 self.driver.find_element_by_id("search-button").click()
1013 # Save screen here
1014 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1015 self.driver.find_element_by_css_selector("i.icon-remove").click()
1016 self.save_screenshot(screenshot_type='selenium', append_name='step4_2')
1017
1018 self.driver.find_element_by_id("edit-columns-button").click()
1019 self.driver.find_element_by_id("depends_on").click()
1020 self.driver.find_element_by_id("layer_version__branch").click()
1021 self.driver.find_element_by_id("layer_version__layer__commit").click()
1022 self.driver.find_element_by_id("depends_by").click()
1023 self.driver.find_element_by_id("edit-columns-button").click()
1024
1025 self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click()
1026 # Check the inverted table by Recipe
1027 # Recipe doesn't have class name
1028 #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]"))
1029 #print inverted_tasks_column_count
1030 #inverted_column_list = self.get_table_column_text_by_column_number(self.table_name, 1)
1031 #print inverted_column_list
1032
1033 #self.driver.find_element_by_partial_link_text("zlib").click()
1034 #self.driver.back()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001035 #self.assertTrue(is_list_inverted(inverted_column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001036 #self.find_element_by_link_text_in_table(self.table_name, 'Recipe').click()
1037
1038 table_head_dict = {'Recipe':'recipe__name', 'Recipe file':'recipe_file', 'Section':'recipe_section', \
1039 'License':'recipe_license', 'Layer':'layer_version__layer__name', \
1040 'Layer branch':'layer_version__branch'}
1041 for key in table_head_dict:
1042 self.find_element_by_link_text_in_table(self.table_name, key).click()
1043 column_list = self.get_table_column_text("class", table_head_dict[key])
1044 if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \
1045 or (not column_list) :
1046 self.find_element_by_link_text_in_table(self.table_name, key).click()
1047 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001048 self.assertTrue(is_list_sequenced(column_list) or is_list_inverted(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001049 self.driver.find_element_by_partial_link_text("acl").click()
1050 self.driver.back()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001051 self.assertTrue(is_list_sequenced(column_list) or is_list_inverted(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001052 # Search text box background text is "Search recipes"
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001053 self.assertTrue(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001054 self.driver.find_element_by_id("search").clear()
1055 self.driver.find_element_by_id("search").send_keys(test_package2)
1056 self.driver.find_element_by_id("search-button").click()
1057 column_search_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001058 self.assertTrue(is_list_sequenced(column_search_list) or is_list_inverted(column_search_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001059 self.driver.find_element_by_css_selector("i.icon-remove").click()
1060 elif is_list_inverted(column_list):
1061 self.find_element_by_link_text_in_table(self.table_name, key).click()
1062 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001063 self.assertTrue(is_list_sequenced(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001064 self.driver.find_element_by_partial_link_text("acl").click()
1065 self.driver.back()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001066 self.assertTrue(is_list_sequenced(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001067 # Search text box background text is "Search recipes"
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001068 self.assertTrue(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001069 self.driver.find_element_by_id("search").clear()
1070 self.driver.find_element_by_id("search").send_keys(test_package2)
1071 self.driver.find_element_by_id("search-button").click()
1072 column_search_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001073 self.assertTrue(is_list_sequenced(column_search_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001074 self.driver.find_element_by_css_selector("i.icon-remove").click()
1075 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001076 self.assertTrue(is_list_sequenced(column_list), msg=("list %s not sequenced" % key))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001077 self.find_element_by_link_text_in_table(self.table_name, key).click()
1078 column_list = self.get_table_column_text("class", table_head_dict[key])
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001079 self.assertTrue(is_list_inverted(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001080 try:
1081 self.driver.find_element_by_partial_link_text("acl").click()
1082 except:
1083 self.driver.find_element_by_partial_link_text("zlib").click()
1084 self.driver.back()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001085 self.assertTrue(is_list_inverted(column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001086 # Search text box background text is "Search recipes"
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001087 self.assertTrue(self.driver.find_element_by_xpath("//*[@id='searchform']/*[@placeholder='Search recipes']"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001088 self.driver.find_element_by_id("search").clear()
1089 self.driver.find_element_by_id("search").send_keys(test_package2)
1090 self.driver.find_element_by_id("search-button").click()
1091 column_search_list = self.get_table_column_text("class", table_head_dict[key])
1092 #print column_search_list
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001093 self.assertTrue(is_list_inverted(column_search_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001094 self.driver.find_element_by_css_selector("i.icon-remove").click()
1095
1096 # Bug 5919
1097 for key in table_head_dict:
1098 print key
1099 self.find_element_by_link_text_in_table(self.table_name, key).click()
1100 self.driver.find_element_by_id("edit-columns-button").click()
1101 self.driver.find_element_by_id(table_head_dict[key]).click()
1102 self.driver.find_element_by_id("edit-columns-button").click()
1103 self.browser_delay()
1104 # After hide the column, the default table should be sorted by Recipe
1105 tasks_column_count = len(self.driver.find_elements_by_partial_link_text("acl"))
1106 #print tasks_column_count
1107 default_column_list = self.get_table_column_text_by_column_number(self.table_name, 1)
1108 #print default_column_list
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001109 self.assertTrue(is_list_sequenced(default_column_list))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001110
1111 self.driver.find_element_by_id("edit-columns-button").click()
1112 self.driver.find_element_by_id("recipe_file").click()
1113 self.driver.find_element_by_id("recipe_section").click()
1114 self.driver.find_element_by_id("recipe_license").click()
1115 self.driver.find_element_by_id("layer_version__layer__name").click()
1116 self.driver.find_element_by_id("edit-columns-button").click()
1117
1118
1119 ##############
1120 # CASE 911 #
1121 ##############
1122 def test_911(self):
1123 self.case_no = self.get_case_number()
1124 self.log.info(' CASE %s log: ' % str(self.case_no))
1125 self.driver.maximize_window()
1126 self.driver.get(self.base_url)
1127 self.driver.find_element_by_link_text("core-image-minimal").click()
1128 self.find_element_by_link_text_in_table('nav', 'Recipes').click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001129 # step 3-5
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001130 self.driver.find_element_by_id("search").clear()
1131 self.driver.find_element_by_id("search").send_keys("lib")
1132 self.driver.find_element_by_id("search-button").click()
1133 # save screen here for observation
1134 self.save_screenshot(screenshot_type='selenium', append_name='step5')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001135 # step 6
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001136 self.driver.find_element_by_css_selector("i.icon-remove").click()
1137 self.driver.find_element_by_id("search").clear()
1138 # we deliberately want "no result" here
1139 self.driver.find_element_by_id("search").send_keys("no such input")
1140 self.driver.find_element_by_id("search-button").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001141 try:
1142 self.find_element_by_text("Show all recipes").click()
1143 except:
1144 self.fail(msg='Could not identify blank page elements')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001145
1146 ##############
1147 # CASE 912 #
1148 ##############
1149 def test_912(self):
1150 self.case_no = self.get_case_number()
1151 self.log.info(' CASE %s log: ' % str(self.case_no))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001152 self.driver.maximize_window()
1153 self.driver.get(self.base_url)
1154 self.driver.find_element_by_link_text("core-image-minimal").click()
1155 self.find_element_by_link_text_in_table('nav', 'Recipes').click()
1156 # step 3
1157 head_list = self.get_table_head_text('otable')
1158 for item in ['Recipe', 'Recipe version', 'Recipe file', 'Section', 'License', 'Layer']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001159 self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
1160 self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001161 self.driver.find_element_by_id("depends_on").click()
1162 self.driver.find_element_by_id("layer_version__branch").click()
1163 self.driver.find_element_by_id("layer_version__layer__commit").click()
1164 self.driver.find_element_by_id("depends_by").click()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001165 self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001166 # check if columns selected above is shown
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001167 check_list = ['Dependencies', 'Layer branch', 'Layer commit', 'Reverse dependencies']
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001168 head_list = self.get_table_head_text('otable')
1169 time.sleep(2)
1170 print head_list
1171 for item in check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001172 self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001173 # un-check 'em all
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001174 self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001175 self.driver.find_element_by_id("depends_on").click()
1176 self.driver.find_element_by_id("layer_version__branch").click()
1177 self.driver.find_element_by_id("layer_version__layer__commit").click()
1178 self.driver.find_element_by_id("depends_by").click()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001179 self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001180 # don't exist any more
1181 head_list = self.get_table_head_text('otable')
1182 for item in check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001183 self.assertFalse(item in head_list, msg=("item %s should not be in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001184
1185
1186 ##############
1187 # CASE 913 #
1188 ##############
1189 def test_913(self):
1190 self.case_no = self.get_case_number()
1191 self.log.info(' CASE %s log: ' % str(self.case_no))
1192 self.driver.maximize_window()
1193 self.driver.get(self.base_url)
1194 self.driver.find_element_by_link_text("core-image-minimal").click()
1195 self.find_element_by_link_text_in_table('nav', 'Recipes').click()
1196 # step 3
1197 head_list = self.get_table_head_text('otable')
1198 for item in ['Recipe', 'Recipe version', 'Recipe file', 'Section', 'License', 'Layer']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001199 self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001200 # step 4
1201 self.driver.find_element_by_id("edit-columns-button").click()
1202 # save screen
1203 self.browser_delay()
1204 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1205 self.driver.find_element_by_id("edit-columns-button").click()
1206
1207
1208 ##############
1209 # CASE 914 #
1210 ##############
1211 def test_914(self):
1212 self.case_no = self.get_case_number()
1213 self.log.info(' CASE %s log: ' % str(self.case_no))
1214 image_type="core-image-minimal"
1215 test_package1="busybox"
1216 test_package2="gdbm"
1217 test_package3="gettext-native"
1218 driver = self.driver
1219 driver.maximize_window()
1220 driver.get(self.base_url)
1221 driver.find_element_by_link_text(image_type).click()
1222 driver.find_element_by_link_text("Recipes").click()
1223 driver.find_element_by_link_text(test_package1).click()
1224
1225 self.table_name = 'information'
1226
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001227 tasks_row_count = len(driver.find_elements_by_xpath("//*[@id='"+self.table_name+"']/table/tbody/tr/td[1]"))
1228 tasks_column_count = len(driver.find_elements_by_xpath("//*[@id='"+self.table_name+"']/table/tbody/tr[1]/td"))
1229 print 'rows: '+str(tasks_row_count)
1230 print 'columns: '+str(tasks_column_count)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001231
1232 Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2)
1233 print ("Tasks_column=", Tasks_column)
1234
1235 key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_package", "do_build"]
1236 i = 0
1237 while i < len(key_tasks):
1238 if key_tasks[i] not in Tasks_column:
1239 print ("Error! Missing key task: %s" % key_tasks[i])
1240 else:
1241 print ("%s is in tasks" % key_tasks[i])
1242 i = i + 1
1243
1244 if Tasks_column.index(key_tasks[0]) != 0:
1245 print ("Error! %s is not in the right position" % key_tasks[0])
1246 else:
1247 print ("%s is in right position" % key_tasks[0])
1248
1249 if Tasks_column[-1] != key_tasks[-1]:
1250 print ("Error! %s is not in the right position" % key_tasks[-1])
1251 else:
1252 print ("%s is in right position" % key_tasks[-1])
1253
1254 driver.find_element_by_partial_link_text("Packages (").click()
1255 packages_name = driver.find_element_by_partial_link_text("Packages (").text
1256 print packages_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001257 packages_num = int(filter(str.isdigit, repr(packages_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001258 print packages_num
1259
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001260 #switch the table to show more than 10 rows at a time
1261 self.driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select").click()
1262 Select(driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select")).select_by_value('150')
1263 self.driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select").send_keys(Keys.ENTER)
1264
1265 packages_row_count = len(driver.find_elements_by_xpath("//*[@id='otable']/tbody/tr/td[1]"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001266 print packages_row_count
1267
1268 if packages_num != packages_row_count:
1269 print ("Error! The packages number is not correct")
1270 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001271 print ("The packages number is correct")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001272
1273 driver.find_element_by_partial_link_text("Build dependencies (").click()
1274 depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
1275 print depends_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001276 depends_num = int(filter(str.isdigit, repr(depends_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001277 print depends_num
1278
1279 if depends_num == 0:
1280 depends_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text)
1281 print depends_message
1282 if depends_message.find("has no build dependencies.") < 0:
1283 print ("Error! The message isn't expected.")
1284 else:
1285 print ("The message is expected")
1286 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001287 depends_row_count = len(driver.find_elements_by_xpath("//*[@id='dependencies']/table/tbody/tr/td[1]"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001288 print depends_row_count
1289 if depends_num != depends_row_count:
1290 print ("Error! The dependent packages number is not correct")
1291 else:
1292 print ("The dependent packages number is correct")
1293
1294 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1295 rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
1296 print rdepends_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001297 rdepends_num = int(filter(str.isdigit, repr(rdepends_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001298 print rdepends_num
1299
1300 if rdepends_num == 0:
1301 rdepends_message = repr(driver.find_element_by_css_selector("#brought-in-by > div.alert.alert-info").text)
1302 print rdepends_message
1303 if rdepends_message.find("has no reverse build dependencies.") < 0:
1304 print ("Error! The message isn't expected.")
1305 else:
1306 print ("The message is expected")
1307 else:
1308 print ("The reverse dependent packages number is correct")
1309
1310 driver.find_element_by_link_text("Recipes").click()
1311 driver.find_element_by_link_text(test_package2).click()
1312 driver.find_element_by_partial_link_text("Packages (").click()
1313 driver.find_element_by_partial_link_text("Build dependencies (").click()
1314 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1315
1316
1317 driver.find_element_by_link_text("Recipes").click()
1318 driver.find_element_by_link_text(test_package3).click()
1319
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001320 native_tasks_row_count = len(driver.find_elements_by_xpath("//*[@id='information']/table/tbody/tr/td[1]"))
1321 native_tasks_column_count = len(driver.find_elements_by_xpath("//*[@id='information']/table/tbody/tr[1]/td"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001322 print native_tasks_row_count
1323 print native_tasks_column_count
1324
1325 Native_Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2)
1326 print ("Native_Tasks_column=", Native_Tasks_column)
1327
1328 native_key_tasks=["do_fetch", "do_unpack", "do_patch", "do_configure", "do_compile", "do_install", "do_build"]
1329 i = 0
1330 while i < len(native_key_tasks):
1331 if native_key_tasks[i] not in Native_Tasks_column:
1332 print ("Error! Missing key task: %s" % native_key_tasks[i])
1333 else:
1334 print ("%s is in tasks" % native_key_tasks[i])
1335 i = i + 1
1336
1337 if Native_Tasks_column.index(native_key_tasks[0]) != 0:
1338 print ("Error! %s is not in the right position" % native_key_tasks[0])
1339 else:
1340 print ("%s is in right position" % native_key_tasks[0])
1341
1342 if Native_Tasks_column[-1] != native_key_tasks[-1]:
1343 print ("Error! %s is not in the right position" % native_key_tasks[-1])
1344 else:
1345 print ("%s is in right position" % native_key_tasks[-1])
1346
1347 driver.find_element_by_partial_link_text("Packages (").click()
1348 native_packages_name = driver.find_element_by_partial_link_text("Packages (").text
1349 print native_packages_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001350 native_packages_num = int(filter(str.isdigit, repr(native_packages_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001351 print native_packages_num
1352
1353 if native_packages_num != 0:
1354 print ("Error! Native task shouldn't have any packages.")
1355 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001356 native_package_message = repr(driver.find_element_by_css_selector("#packages-built > div.alert.alert-info").text)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001357 print native_package_message
1358 if native_package_message.find("does not build any packages.") < 0:
1359 print ("Error! The message for native task isn't expected.")
1360 else:
1361 print ("The message for native task is expected.")
1362
1363 driver.find_element_by_partial_link_text("Build dependencies (").click()
1364 native_depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
1365 print native_depends_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001366 native_depends_num = int(filter(str.isdigit, repr(native_depends_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001367 print native_depends_num
1368
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001369 native_depends_row_count = len(driver.find_elements_by_xpath("//*[@id='dependencies']/table/tbody/tr/td[1]"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001370 print native_depends_row_count
1371
1372 if native_depends_num != native_depends_row_count:
1373 print ("Error! The dependent packages number is not correct")
1374 else:
1375 print ("The dependent packages number is correct")
1376
1377 driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
1378 native_rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
1379 print native_rdepends_name
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001380 native_rdepends_num = int(filter(str.isdigit, repr(native_rdepends_name)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001381 print native_rdepends_num
1382
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001383 native_rdepends_row_count = len(driver.find_elements_by_xpath("//*[@id='brought-in-by']/table/tbody/tr/td[1]"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001384 print native_rdepends_row_count
1385
1386 if native_rdepends_num != native_rdepends_row_count:
1387 print ("Error! The reverse dependent packages number is not correct")
1388 else:
1389 print ("The reverse dependent packages number is correct")
1390
1391 driver.find_element_by_link_text("Recipes").click()
1392
1393
1394 ##############
1395 # CASE 915 #
1396 ##############
1397 def test_915(self):
1398 self.case_no = self.get_case_number()
1399 self.log.info(' CASE %s log: ' % str(self.case_no))
1400 self.driver.maximize_window()
1401 self.driver.get(self.base_url)
1402 self.driver.find_element_by_link_text("core-image-minimal").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001403 # step 3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001404 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1405 self.driver.find_element_by_link_text("BitBake variables").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001406 # step 4
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001407 self.driver.find_element_by_id("search").clear()
1408 self.driver.find_element_by_id("search").send_keys("lib")
1409 self.driver.find_element_by_id("search-button").click()
1410 # save screen to see result
1411 self.browser_delay()
1412 self.save_screenshot(screenshot_type='selenium', append_name='step4')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001413 # step 5
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001414 self.driver.find_element_by_css_selector("i.icon-remove").click()
1415 head_list = self.get_table_head_text('otable')
1416 print head_list
1417 print len(head_list)
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001418 self.assertTrue(head_list == ['Variable', 'Value', 'Set in file', 'Description'], \
1419 msg=("head row contents wrong"))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001420 # step 8
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001421 # search other string. and click "Variable" to re-sort, check if table
1422 # head is still the same
1423 self.driver.find_element_by_id("search").clear()
1424 self.driver.find_element_by_id("search").send_keys("poky")
1425 self.driver.find_element_by_id("search-button").click()
1426 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1427 head_list = self.get_table_head_text('otable')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001428 self.assertTrue(head_list == ['Variable', 'Value', 'Set in file', 'Description'], \
1429 msg=("head row contents wrong"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001430 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1431 head_list = self.get_table_head_text('otable')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001432 self.assertTrue(head_list == ['Variable', 'Value', 'Set in file', 'Description'], \
1433 msg=("head row contents wrong"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001434
1435
1436 ##############
1437 # CASE 916 #
1438 ##############
1439 def test_916(self):
1440 self.case_no = self.get_case_number()
1441 self.log.info(' CASE %s log: ' % str(self.case_no))
1442 self.driver.maximize_window()
1443 self.driver.get(self.base_url)
1444 self.driver.find_element_by_link_text("core-image-minimal").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001445 # step 2-3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001446 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1447 self.driver.find_element_by_link_text("BitBake variables").click()
1448 variable_list = self.get_table_column_text('class', 'variable_name')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001449 self.assertTrue(is_list_sequenced(variable_list), msg=("list not in order"))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001450 # step 4
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001451 self.find_element_by_link_text_in_table('otable', 'Variable').click()
1452 variable_list = self.get_table_column_text('class', 'variable_name')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001453 self.assertTrue(is_list_inverted(variable_list), msg=("list not inverted"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001454 self.find_element_by_link_text_in_table('otable', 'Variable').click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001455 # step 5
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001456 # searching won't change the sequentiality
1457 self.driver.find_element_by_id("search").clear()
1458 self.driver.find_element_by_id("search").send_keys("lib")
1459 self.driver.find_element_by_id("search-button").click()
1460 variable_list = self.get_table_column_text('class', 'variable_name')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001461 self.assertTrue(is_list_sequenced(variable_list), msg=("list not in order"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001462
1463
1464 ##############
1465 # CASE 923 #
1466 ##############
1467 def test_923(self):
1468 self.case_no = self.get_case_number()
1469 self.log.info(' CASE %s log: ' % str(self.case_no))
1470 self.driver.maximize_window()
1471 self.driver.get(self.base_url)
1472 # Step 2
1473 # default sequence in "Completed on" column is inverted
1474 c_list = self.get_table_column_text('class', 'completed_on')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001475 self.assertTrue(is_list_inverted(c_list), msg=("list not inverted"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001476 # step 3
1477 self.driver.find_element_by_id("edit-columns-button").click()
1478 self.driver.find_element_by_id("started_on").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001479 self.driver.find_element_by_id("time").click()
1480 self.driver.find_element_by_id("edit-columns-button").click()
1481 head_list = self.get_table_head_text('otable')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001482 for item in ['Outcome', 'Recipe', 'Machine', 'Started on', 'Completed on', 'Failed tasks', 'Errors', 'Warnings', 'Time', "Image files", "Project"]:
1483 self.failUnless(item in head_list, msg=item+' is missing from table head.')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001484
1485
1486 ##############
1487 # CASE 924 #
1488 ##############
1489 def test_924(self):
1490 self.case_no = self.get_case_number()
1491 self.log.info(' CASE %s log: ' % str(self.case_no))
1492 self.driver.maximize_window()
1493 self.driver.get(self.base_url)
1494 # Please refer to case 924 requirement
1495 # default sequence in "Completed on" column is inverted
1496 c_list = self.get_table_column_text('class', 'completed_on')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001497 self.assertTrue(is_list_inverted(c_list), msg=("list not inverted"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001498 # Step 4
1499 # click Errors , order in "Completed on" should be disturbed. Then hide
1500 # error column to check if order in "Completed on" can be restored
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001501#THIS TEST IS NO LONGER VALID DUE TO DESIGN CHANGES. LEAVING IN PENDING UPDATES TO DESIGN
1502 #self.find_element_by_link_text_in_table('otable', 'Errors').click()
1503 #self.driver.find_element_by_id("edit-columns-button").click()
1504 #self.driver.find_element_by_id("errors_no").click()
1505 #self.driver.find_element_by_id("edit-columns-button").click()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001506 # Note: without time.sleep here, there'll be unpredictable error..TBD
1507 time.sleep(1)
1508 c_list = self.get_table_column_text('class', 'completed_on')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001509 self.assertTrue(is_list_inverted(c_list), msg=("list not inverted"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001510
1511
1512 ##############
1513 # CASE 940 #
1514 ##############
1515 def test_940(self):
1516 self.case_no = self.get_case_number()
1517 self.log.info(' CASE %s log: ' % str(self.case_no))
1518 self.driver.maximize_window()
1519 self.driver.get(self.base_url)
1520 self.driver.find_element_by_link_text("core-image-minimal").click()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001521 # Step 2-3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001522 self.find_element_by_link_text_in_table('nav', 'Packages').click()
1523 check_head_list = ['Package', 'Package version', 'Size', 'Recipe']
1524 head_list = self.get_table_head_text('otable')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001525 self.assertTrue(head_list == check_head_list, msg=("head row not as expected"))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001526 # Step 4
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001527 # pulldown menu
1528 option_ids = ['recipe__layer_version__layer__name', 'recipe__layer_version__branch', \
1529 'recipe__layer_version__layer__commit', 'license', 'recipe__version']
1530 self.driver.find_element_by_id("edit-columns-button").click()
1531 for item in option_ids:
1532 if not self.driver.find_element_by_id(item).is_selected():
1533 self.driver.find_element_by_id(item).click()
1534 self.driver.find_element_by_id("edit-columns-button").click()
1535 # save screen here to observe that 'Package' and 'Package version' is
1536 # not selectable
1537 self.browser_delay()
1538 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1539
1540
1541 ##############
1542 # CASE 941 #
1543 ##############
1544 def test_941(self):
1545 self.case_no = self.get_case_number()
1546 self.log.info(' CASE %s log: ' % str(self.case_no))
1547 self.driver.maximize_window()
1548 self.driver.get(self.base_url)
1549 self.driver.find_element_by_link_text("core-image-minimal").click()
1550 # Step 2-3
1551 self.find_element_by_link_text_in_table('nav', 'Packages').click()
1552 # column -- Package
1553 column_list = self.get_table_column_text_by_column_number('otable', 1)
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001554 self.assertTrue(is_list_sequenced(column_list), msg=("list not in order"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001555 self.find_element_by_link_text_in_table('otable', 'Size').click()
1556
1557
1558 ##############
1559 # CASE 942 #
1560 ##############
1561 def test_942(self):
1562 self.case_no = self.get_case_number()
1563 self.log.info(' CASE %s log: ' % str(self.case_no))
1564 self.driver.maximize_window()
1565 self.driver.get(self.base_url)
1566 self.driver.find_element_by_link_text("core-image-minimal").click()
1567 self.driver.find_element_by_link_text("Packages").click()
1568 #get initial table header
1569 head_list = self.get_table_head_text('otable')
1570 #remove the Recipe column from table header
1571 self.driver.find_element_by_id("edit-columns-button").click()
1572 self.driver.find_element_by_id("recipe__name").click()
1573 self.driver.find_element_by_id("edit-columns-button").click()
1574 #get modified table header
1575 new_head = self.get_table_head_text('otable')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001576 self.assertTrue(head_list > new_head)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001577
1578 ##############
1579 # CASE 943 #
1580 ##############
1581 def test_943(self):
1582 self.case_no = self.get_case_number()
1583 self.log.info(' CASE %s log: ' % str(self.case_no))
1584 self.driver.maximize_window()
1585 self.driver.get(self.base_url)
1586 self.driver.find_element_by_link_text("core-image-minimal").click()
1587 self.driver.find_element_by_link_text("Packages").click()
1588 #search for the "bash" package -> this should definitely be present
1589 self.driver.find_element_by_id("search").clear()
1590 self.driver.find_element_by_id("search").send_keys("bash")
1591 self.driver.find_element_by_id("search-button").click()
1592 #check for the search result message "XX packages found"
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001593 self.assertTrue(self.is_text_present("packages found"), msg=("no packages found text"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001594
1595
1596 ##############
1597 # CASE 944 #
1598 ##############
1599 def test_944(self):
1600 self.case_no = self.get_case_number()
1601 self.log.info(' CASE %s log: ' % str(self.case_no))
1602 self.driver.maximize_window()
1603 self.driver.get(self.base_url)
1604 self.driver.find_element_by_link_text("core-image-minimal").click()
1605 # step 1: test Recipes page stuff
1606 self.driver.find_element_by_link_text("Recipes").click()
1607 # for these 3 items, default status is not-checked
1608 self.driver.find_element_by_id("edit-columns-button").click()
1609 self.driver.find_element_by_id("layer_version__branch").click()
1610 self.driver.find_element_by_id("layer_version__layer__commit").click()
1611 self.driver.find_element_by_id("edit-columns-button").click()
1612 # otable is the recipes table here
1613 otable_head_text = self.get_table_head_text('otable')
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001614 for item in ["Layer", "Layer branch", "Layer commit"]:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001615 self.failIf(item not in otable_head_text, msg=item+' not in table head.')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001616 # click the fist recipe, whatever it is
1617 self.get_table_element("otable", 1, 1).click()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001618 self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Recipe file"]), \
1619 msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001620
1621 # step 2: test Packages page stuff. almost same as above
1622 self.driver.back()
1623 self.browser_delay()
1624 self.driver.find_element_by_link_text("Packages").click()
1625 self.driver.find_element_by_id("edit-columns-button").click()
1626 self.driver.find_element_by_id("recipe__layer_version__layer__name").click()
1627 self.driver.find_element_by_id("recipe__layer_version__branch").click()
1628 self.driver.find_element_by_id("recipe__layer_version__layer__commit").click()
1629 self.driver.find_element_by_id("edit-columns-button").click()
1630 otable_head_text = self.get_table_head_text("otable")
1631 for item in ["Layer", "Layer branch", "Layer commit"]:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001632 self.assertFalse(item not in otable_head_text, msg=("item %s should be in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001633 # click the fist recipe, whatever it is
1634 self.get_table_element("otable", 1, 1).click()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001635 self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit"]), \
1636 msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001637
1638 # step 3: test Packages core-image-minimal(images) stuff. almost same as above. Note when future element-id changes...
1639 self.driver.back()
1640 self.driver.find_element_by_link_text("core-image-minimal").click()
1641 self.driver.find_element_by_id("edit-columns-button").click()
1642 self.driver.find_element_by_id("layer_name").click()
1643 self.driver.find_element_by_id("layer_branch").click()
1644 self.driver.find_element_by_id("layer_commit").click()
1645 self.driver.find_element_by_id("edit-columns-button").click()
1646 otable_head_text = self.get_table_head_text("otable")
1647 for item in ["Layer", "Layer branch", "Layer commit"]:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001648 self.assertFalse(item not in otable_head_text, msg=("item %s should be in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001649 # click the fist recipe, whatever it is
1650 self.get_table_element("otable", 1, 1).click()
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001651 self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit"]), \
1652 msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001653
1654 # step 4: check Configuration page
1655 self.driver.back()
1656 self.driver.find_element_by_link_text("Configuration").click()
1657 otable_head_text = self.get_table_head_text()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001658 self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit"]), \
1659 msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001660
1661
1662 ##############
1663 # CASE 945 #
1664 ##############
1665 def test_945(self):
1666 self.case_no = self.get_case_number()
1667 self.log.info(' CASE %s log: ' % str(self.case_no))
1668 self.driver.maximize_window()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001669 for item in ["Packages", "Recipes", "Tasks"]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001670 self.driver.get(self.base_url)
1671 self.driver.find_element_by_link_text("core-image-minimal").click()
1672 self.driver.find_element_by_link_text(items).click()
1673
1674 # this may be page specific. If future page content changes, try to replace it with new xpath
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001675 xpath_showrows = "/html/body/div[4]/div/div/div[2]/div[2]/div[2]/div/div/div[2]/select"
1676 xpath_table = "html/body/div[4]/div/div/div[2]/div[2]/table/tbody"#"id=('otable')/tbody"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001677 self.driver.find_element_by_xpath(xpath_showrows).click()
1678 rows_displayed = int(self.driver.find_element_by_xpath(xpath_showrows + "/option[2]").text)
1679
1680 # 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
1681 # Sure we can use driver.get(url) to refresh page, but since page will vary, we use click link text here
1682 self.driver.find_element_by_link_text(items).click()
1683 Select(self.driver.find_element_by_css_selector("select.pagesize")).select_by_visible_text(str(rows_displayed))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001684 self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
1685 self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001686
1687 # click 1st package, then go back to check if it's still those rows shown.
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001688 self.driver.find_element_by_xpath(xpath_otable + "/tr[1]/td[1]/a").click()
1689 time.sleep(3)
1690 self.driver.find_element_by_link_text(item).click()
1691 self.assertTrue(self.is_element_present(By.XPATH, xpath_otable + "/tr[" + str(option_tobeselected) +"]"),\
1692 msg=("Row %d should exist" %option_tobeselected))
1693 self.assertFalse(self.is_element_present(By.XPATH, xpath_otable + "/tr[" + str(option_tobeselected+1) +"]"),\
1694 msg=("Row %d should not exist" %(option_tobeselected+1)))
1695
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001696
1697
1698 ##############
1699 # CASE 946 #
1700 ##############
1701 def test_946(self):
1702 self.case_no = self.get_case_number()
1703 self.log.info(' CASE %s log: ' % str(self.case_no))
1704 self.driver.maximize_window()
1705 self.driver.get(self.base_url)
1706 self.driver.find_element_by_link_text("core-image-minimal").click()
1707 self.driver.find_element_by_link_text("Configuration").click()
1708 # step 3-4
1709 check_list = ["Summary", "BitBake variables"]
1710 for item in check_list:
1711 if not self.is_element_present(how=By.LINK_TEXT, what=item):
1712 self.log.error("%s not found" %item)
1713 if not self.is_text_present(['Layers', 'Layer', 'Layer branch', 'Layer commit']):
1714 self.log.error("text not found")
1715 # step 5
1716 self.driver.find_element_by_link_text("BitBake variables").click()
1717 if not self.is_text_present(['Variable', 'Value', 'Set in file', 'Description']):
1718 self.log.error("text not found")
1719 # This may be unstable because it's page-specific
1720 # step 6: this is how we find filter beside "Set in file"
1721 temp_element = self.find_element_by_text_in_table('otable', "Set in file")
1722 temp_element.find_element_by_xpath("..//*/a/i[@class='icon-filter filtered']").click()
1723 self.browser_delay()
1724 self.driver.find_element_by_xpath("(//input[@name='filter'])[3]").click()
1725 btns = self.driver.find_elements_by_css_selector("button.btn.btn-primary")
1726 for btn in btns:
1727 try:
1728 btn.click()
1729 break
1730 except:
1731 pass
1732 # save screen here
1733 self.browser_delay()
1734 self.save_screenshot(screenshot_type='selenium', append_name='step6')
1735 self.driver.find_element_by_id("edit-columns-button").click()
1736 # save screen here
1737 # step 7
1738 # we should manually check the step 6-8 result using screenshot
1739 self.browser_delay()
1740 self.save_screenshot(screenshot_type='selenium', append_name='step7')
1741 self.driver.find_element_by_id("edit-columns-button").click()
1742 # step 9
1743 # click the 1st item, no matter what it is
1744 self.driver.find_element_by_xpath("//*[@id='otable']/tbody/tr[1]/td[1]/a").click()
1745 # give it 1 sec so the pop-up becomes the "active_element"
1746 time.sleep(1)
1747 element = self.driver.switch_to.active_element
1748 check_list = ['Order', 'Configuration file', 'Operation', 'Line number']
1749 for item in check_list:
1750 if item not in element.text:
1751 self.log.error("%s not found" %item)
1752 # any better way to close this pop-up? ... TBD
1753 element.find_element_by_class_name("close").click()
1754 # step 10 : need to manually check "Yocto Manual" in saved screen
1755 self.driver.find_element_by_css_selector("i.icon-share.get-info").click()
1756 # save screen here
1757 time.sleep(5)
1758 self.save_screenshot(screenshot_type='native', append_name='step10')
1759
1760
1761 ##############
1762 # CASE 947 #
1763 ##############
1764 def test_947(self):
1765 self.case_no = self.get_case_number()
1766 self.log.info(' CASE %s log: ' % str(self.case_no))
1767 self.driver.maximize_window()
1768 self.driver.get(self.base_url)
1769 self.driver.find_element_by_link_text("core-image-minimal").click()
1770 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1771 # step 2
1772 self.driver.find_element_by_link_text("BitBake variables").click()
1773 # step 3
1774 def xpath_option(column_name):
1775 # return xpath of options under "Edit columns" button
1776 return self.shortest_xpath('id', 'navTab') + self.shortest_xpath('id', 'editcol') \
1777 + self.shortest_xpath('id', column_name)
1778 self.driver.find_element_by_id('edit-columns-button').click()
1779 # by default, option "Description" and "Set in file" were checked
1780 self.driver.find_element_by_xpath(xpath_option('description')).click()
1781 self.driver.find_element_by_xpath(xpath_option('file')).click()
1782 self.driver.find_element_by_id('edit-columns-button').click()
1783 check_list = ['Description', 'Set in file']
1784 head_list = self.get_table_head_text('otable')
1785 for item in check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001786 self.assertFalse(item in head_list, msg=("item %s should not be in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001787 # check these 2 options and verify again
1788 self.driver.find_element_by_id('edit-columns-button').click()
1789 self.driver.find_element_by_xpath(xpath_option('description')).click()
1790 self.driver.find_element_by_xpath(xpath_option('file')).click()
1791 self.driver.find_element_by_id('edit-columns-button').click()
1792 head_list = self.get_table_head_text('otable')
1793 for item in check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001794 self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001795
1796
1797 ##############
1798 # CASE 948 #
1799 ##############
1800 def test_948(self):
1801 self.case_no = self.get_case_number()
1802 self.log.info(' CASE %s log: ' % str(self.case_no))
1803 self.driver.maximize_window()
1804 self.driver.get(self.base_url)
1805 self.driver.find_element_by_link_text("core-image-minimal").click()
1806 self.find_element_by_link_text_in_table('nav', 'Configuration').click()
1807 self.driver.find_element_by_link_text("BitBake variables").click()
1808 #get number of variables visible by default
1809 number_before_search = self.driver.find_element_by_class_name('page-header').text
1810 # search for a while...
1811 self.driver.find_element_by_id("search").clear()
1812 self.driver.find_element_by_id("search").send_keys("BB")
1813 self.driver.find_element_by_id("search-button").click()
1814 #get number of variables visible after search
1815 number_after_search = self.driver.find_element_by_class_name('page-header').text
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001816 self.assertTrue(number_before_search > number_after_search, msg=("items should be less after search"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001817
1818
1819 ##############
1820 # CASE 949 #
1821 ##############
1822 def test_949(self):
1823 self.case_no = self.get_case_number()
1824 self.log.info(' CASE %s log: ' % str(self.case_no))
1825 self.driver.maximize_window()
1826 self.driver.get(self.base_url)
1827 self.driver.find_element_by_link_text("core-image-minimal").click()
1828 self.find_element_by_link_text_in_table('nav', 'core-image-minimal').click()
1829 # step 3
1830 try:
1831 self.driver.find_element_by_partial_link_text("Packages included")
1832 self.driver.find_element_by_partial_link_text("Directory structure")
1833 except Exception,e:
1834 self.log.error(e)
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001835 self.assertFalse(True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001836 # step 4
1837 head_list = self.get_table_head_text('otable')
1838 for item in ['Package', 'Package version', 'Size', 'Dependencies', 'Reverse dependencies', 'Recipe']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001839 self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001840 # step 5-6
1841 self.driver.find_element_by_id("edit-columns-button").click()
1842 selectable_class = 'checkbox'
1843 # minimum-table : means unselectable items
1844 unselectable_class = 'checkbox muted'
1845 selectable_check_list = ['Dependencies', 'Layer', 'Layer branch', 'Layer commit', \
1846 'License', 'Recipe', 'Recipe version', 'Reverse dependencies', \
1847 'Size', 'Size over total (%)']
1848 unselectable_check_list = ['Package', 'Package version']
1849 selectable_list = list()
1850 unselectable_list = list()
1851 selectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + selectable_class + "']")
1852 unselectable_elements = self.driver.find_elements_by_xpath("//*[@id='editcol']//*[@class='" + unselectable_class + "']")
1853 for element in selectable_elements:
1854 selectable_list.append(element.text)
1855 for element in unselectable_elements:
1856 unselectable_list.append(element.text)
1857 # check them
1858 for item in selectable_check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001859 self.assertTrue(item in selectable_list, msg=("%s not found in dropdown menu" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001860 for item in unselectable_check_list:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001861 self.assertTrue(item in unselectable_list, msg=("%s not found in dropdown menu" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001862 self.driver.find_element_by_id("edit-columns-button").click()
1863 # step 7
1864 self.driver.find_element_by_partial_link_text("Directory structure").click()
1865 head_list = self.get_table_head_text('dirtable')
1866 for item in ['Directory / File', 'Symbolic link to', 'Source package', 'Size', 'Permissions', 'Owner', 'Group']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001867 self.assertTrue(item in head_list, msg=("%s not found in Directory structure table head" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001868
1869 ##############
1870 # CASE 950 #
1871 ##############
1872 def test_950(self):
1873 self.case_no = self.get_case_number()
1874 self.log.info(' CASE %s log: ' % str(self.case_no))
1875 self.driver.maximize_window()
1876 self.driver.get(self.base_url)
1877 # step3&4: so far we're not sure if there's "successful build" or "failed
1878 # build".If either of them doesn't exist, we can still go on other steps
1879 check_list = ['Configuration', 'Tasks', 'Recipes', 'Packages', 'Time', 'CPU usage', 'Disk I/O']
1880 has_successful_build = 1
1881 has_failed_build = 1
1882 try:
1883 pass_icon = self.driver.find_element_by_xpath("//*[@class='icon-ok-sign success']")
1884 except Exception:
1885 self.log.info("no successful build exists")
1886 has_successful_build = 0
1887 pass
1888 if has_successful_build:
1889 pass_icon.click()
1890 # save screen here to check if it matches requirement.
1891 self.browser_delay()
1892 self.save_screenshot(screenshot_type='selenium', append_name='step3_1')
1893 for item in check_list:
1894 try:
1895 self.find_element_by_link_text_in_table('nav', item)
1896 except Exception:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001897 self.assertFalse(True, msg=("link %s cannot be found in the page" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001898 # step 6
1899 check_list_2 = ['Packages included', 'Total package size', \
1900 'License manifest', 'Image files']
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001901 self.assertTrue(self.is_text_present(check_list_2), msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001902 self.driver.back()
1903 try:
1904 fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']")
1905 except Exception:
1906 has_failed_build = 0
1907 self.log.info("no failed build exists")
1908 pass
1909 if has_failed_build:
1910 fail_icon.click()
1911 # save screen here to check if it matches requirement.
1912 self.browser_delay()
1913 self.save_screenshot(screenshot_type='selenium', append_name='step3_2')
1914 for item in check_list:
1915 try:
1916 self.find_element_by_link_text_in_table('nav', item)
1917 except Exception:
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001918 self.assertFalse(True, msg=("link %s cannot be found in the page" % item))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001919 # step 7 involved
1920 check_list_3 = ['Machine', 'Distro', 'Layers', 'Total number of tasks', 'Tasks executed', \
1921 'Tasks not executed', 'Reuse', 'Recipes built', 'Packages built']
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001922 self.assertTrue(self.is_text_present(check_list_3), msg=("text not in web page"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001923 self.driver.back()
1924
1925
1926 ##############
1927 # CASE 951 #
1928 ##############
1929 def test_951(self):
1930 self.case_no = self.get_case_number()
1931 self.log.info(' CASE %s log: ' % str(self.case_no))
1932 self.driver.maximize_window()
1933 self.driver.get(self.base_url)
1934 # currently test case itself isn't responsible for creating "1 successful and
1935 # 1 failed build"
1936 has_successful_build = 1
1937 has_failed_build = 1
1938 try:
1939 fail_icon = self.driver.find_element_by_xpath("//*[@class='icon-minus-sign error']")
1940 except Exception:
1941 has_failed_build = 0
1942 self.log.info("no failed build exists")
1943 pass
1944 # if there's failed build, we can proceed
1945 if has_failed_build:
1946 self.driver.find_element_by_partial_link_text("error").click()
1947 self.driver.back()
1948 # not sure if there "must be" some warnings, so here save a screen
1949 self.browser_delay()
1950 self.save_screenshot(screenshot_type='selenium', append_name='step4')
1951
1952
1953 ##############
1954 # CASE 955 #
1955 ##############
1956 def test_955(self):
1957 self.case_no = self.get_case_number()
1958 self.log.info(' CASE %s log: ' % str(self.case_no))
1959 self.driver.maximize_window()
1960 self.driver.get(self.base_url)
1961 self.log.info(" You should manually create all images before test starts!")
1962 # So far the case itself is not responsable for creating all sorts of images.
1963 # So assuming they are already there
1964 # step 2
1965 self.driver.find_element_by_link_text("core-image-minimal").click()
1966 # save screen here to see the page component
1967
1968
1969 ##############
1970 # CASE 956 #
1971 ##############
1972 def test_956(self):
1973 self.case_no = self.get_case_number()
1974 self.log.info(' CASE %s log: ' % str(self.case_no))
1975 self.driver.maximize_window()
1976 self.driver.get(self.base_url)
1977 # step 2-3 need to run manually
1978 self.log.info("step 2-3: checking the help message when you hover on help icon of target,\
1979 tasks, recipes, packages need to run manually")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001980 self.driver.find_element_by_partial_link_text("Manual").click()
1981 if not self.is_text_present("Manual"):
1982 self.log.error("please check [Toaster manual] link on page")
1983 self.failIf(True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001984
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001985####################################################################################################
1986# Starting backend tests ###########################################################################
1987####################################################################################################
1988
1989 ##############
1990 # CASE 1066 #
1991 ##############
1992 def test_1066(self):
1993 self.case_no = self.get_case_number()
1994 self.log.info(' CASE %s log: ' % str(self.case_no))
1995 con=sqlite.connect('toaster.sqlite')
1996 cursor = con.cursor()
1997 query = "select count(name) from orm_project a, auth_user b where a.user_id = b.id and b.username='_anonuser';"
1998 cursor.execute(query)
1999 data = cursor.fetchone()
2000 self.failUnless(data >= 1)
2001
2002
2003 ##############
2004 # CASE 1071 #
2005 ##############
2006 def test_1071(self):
2007 self.case_no = self.get_case_number()
2008 self.log.info(' CASE %s log: ' % str(self.case_no))
2009 con=sqlite.connect('toaster.sqlite')
2010 cursor = con.cursor()
2011 query = "select name from orm_release;"
2012 cursor.execute(query)
2013 data = cursor.fetchall()
2014 for i in range(0,4):
2015 data[i] = data[i][0]
2016 data.sort()
2017 print data
2018 json_parse = json.loads(open('toasterconf.json').read())
2019 json_data = []
2020 for i in range (0,4):
2021 json_data.append(json_parse['releases'][i]['name'])
2022 json_data.sort()
2023 print json_data
2024 self.failUnless(data == json_data)
2025
2026 ##############
2027 # CASE 1072 #
2028 ##############
2029 def test_1072(self):
2030 self.case_no = self.get_case_number()
2031 self.log.info(' CASE %s log: ' % str(self.case_no))
2032 con=sqlite.connect('toaster.sqlite')
2033 cursor = con.cursor()
2034 query = "select value from orm_toastersetting where name like 'DEFCONF%';"
2035 cursor.execute(query)
2036 data = cursor.fetchall()
2037 for i in range(0,6):
2038 data[i] = data[i][0]
2039 print data
2040 json_parse = json.loads(open('toasterconf.json').read())
2041 json_data=json_parse['config']
2042 json_data = json_data.values()
2043 print json_data
2044 self.failUnless(data == json_data)
2045
2046
2047 ##############
2048 # CASE 1074 #
2049 ##############
2050 def test_1074(self):
2051 self.case_no = self.get_case_number()
2052 self.log.info(' CASE %s log: ' % str(self.case_no))
2053 con=sqlite.connect('toaster.sqlite')
2054 cursor = con.cursor()
2055 query = "select name from orm_layersource;"
2056 cursor.execute(query)
2057 data = cursor.fetchall()
2058 for i in range(0,3):
2059 data[i] = data[i][0]
2060 print data
2061 json_parse = json.loads(open('toasterconf.json').read())
2062 json_data = []
2063 for i in range(0,3):
2064 json_data.append(json_parse['layersources'][i]['name'])
2065 print json_data
2066 self.failUnless(set(data) == set(json_data))
2067
2068 ##############
2069 # CASE 1075 #
2070 ##############
2071 def test_1075(self):
2072 self.case_no = self.get_case_number()
2073 self.log.info(' CASE %s log: ' % str(self.case_no))
2074 con=sqlite.connect('toaster.sqlite')
2075 cursor = con.cursor()
2076 query = "select value from orm_toastersetting where name like 'DEFAULT_RELEASE';"
2077 cursor.execute(query)
2078 data = cursor.fetchall()
2079 data = data[0][0]
2080 print data
2081 json_parse = json.loads(open('toasterconf.json').read())
2082 json_data = json_parse['defaultrelease']
2083 print json_data
2084 self.failUnless(set(data) == set(json_data))
2085
2086 ##############
2087 # CASE 1076 #
2088 ##############
2089 def test_1076(self):
2090 self.case_no = self.get_case_number()
2091 self.log.info(' CASE %s log: ' % str(self.case_no))
2092
2093 print 'Checking branches for "Local Yocto Project"'
2094 con=sqlite.connect('toaster.sqlite')
2095 cursor = con.cursor()
2096 query = "select name from orm_branch where layer_source_id=1;"
2097 cursor.execute(query)
2098 data = cursor.fetchall()
2099 lenght = len(data)
2100 try:
2101 for i in range(0,lenght):
2102 data[i] = data[i][0]
2103 except:
2104 pass
2105 print data
2106 json_parse = json.loads(open('toasterconf.json').read())
2107 json_location = json_parse['layersources'][0]['name']
2108 print json_location
2109 json_data = json_parse['layersources'][0]['branches']
2110 print json_data
2111 self.failUnless(set(data) == set(json_data))
2112
2113 print 'Checking branches for "OpenEmbedded"'
2114 con=sqlite.connect('toaster.sqlite')
2115 cursor = con.cursor()
2116 query = "select name from orm_branch where layer_source_id=3;"
2117 cursor.execute(query)
2118 data = cursor.fetchall()
2119 lenght = len(data)
2120 for i in range(0,lenght):
2121 data[i] = data[i][0]
2122 print data
2123 json_parse = json.loads(open('toasterconf.json').read())
2124 json_location = json_parse['layersources'][1]['name']
2125 print json_location
2126 json_data = json_parse['layersources'][1]['branches']
2127 print json_data
2128 self.failUnless(set(data) == set(json_data))
2129
2130 print 'Checking branches for "Imported layers"'
2131 con=sqlite.connect('toaster.sqlite')
2132 cursor = con.cursor()
2133 query = "select name from orm_branch where layer_source_id=2;"
2134 cursor.execute(query)
2135 data = cursor.fetchall()
2136 lenght = len(data)
2137 for i in range(0,lenght):
2138 data[i] = data[i][0]
2139 print data
2140 json_parse = json.loads(open('toasterconf.json').read())
2141 json_location = json_parse['layersources'][2]['name']
2142 print json_location
2143 json_data = json_parse['layersources'][2]['branches']
2144 print json_data
2145 self.failUnless(set(data) == set(json_data))
2146
2147
2148 ##############
2149 # CASE 1077 #
2150 ##############
2151 def test_1077(self):
2152 self.case_no = self.get_case_number()
2153 self.log.info(' CASE %s log: ' % str(self.case_no))
2154 con=sqlite.connect('toaster.sqlite')
2155 cursor = con.cursor()
2156 query = "select name from orm_bitbakeversion;"
2157 cursor.execute(query)
2158 data = cursor.fetchall()
2159 for i in range(0,4):
2160 data[i] = data[i][0]
2161 print data
2162 json_parse = json.loads(open('toasterconf.json').read())
2163 json_data = []
2164 for i in range(0,4):
2165 json_data.append(json_parse['bitbake'][i]['name'])
2166 print json_data
2167 self.failUnless(set(data) == set(json_data))
2168
2169 ##############
2170 # CASE 1083 #
2171 ##############
2172 def test_1083(self):
2173 self.case_no = self.get_case_number()
2174 self.log.info(' CASE %s log: ' % str(self.case_no))
2175 self.driver.maximize_window()
2176 self.driver.get(self.base_url)
2177 self.driver.find_element_by_id("new-project-button").click()
2178 self.driver.find_element_by_id("new-project-name").send_keys("new-test-project")
2179 self.driver.find_element_by_id("create-project-button").click()
2180 con=sqlite.connect('toaster.sqlite')
2181 cursor = con.cursor()
2182 query = "select count(name) from orm_project where name = 'new-test-project';"
2183 cursor.execute(query)
2184 data = cursor.fetchone()
2185 print 'data: %s' % data
2186 self.failUnless(data >= 1)
2187
2188 ##############
2189 # CASE 1084 #
2190 ##############
2191 def test_1084(self):
2192 self.case_no = self.get_case_number()
2193 self.log.info(' CASE %s log: ' % str(self.case_no))
2194 self.driver.maximize_window()
2195 self.driver.get(self.base_url)
2196 self.driver.find_element_by_id("new-project-button").click()
2197 self.driver.find_element_by_id("new-project-name").send_keys("new-default-project")
2198 self.driver.find_element_by_id("create-project-button").click()
2199 con=sqlite.connect('toaster.sqlite')
2200 cursor = con.cursor()
2201 query = "select a.name from orm_release a, orm_project b where a.id = b.release_id and b.name = 'new-default-project' limit 1;"
2202 cursor.execute(query)
2203 db_data = str(cursor.fetchone()[0])
2204 json_parse = json.loads(open('toasterconf.json').read())
2205 json_data = str(json_parse['defaultrelease'])
2206 self.failUnless(db_data == json_data)
2207
2208 ##############
2209 # CASE 1088 #
2210 ##############
2211 def test_1088(self):
2212 self.case_no = self.get_case_number()
2213 self.log.info(' CASE %s log: ' % str(self.case_no))
2214 self.driver.maximize_window()
2215 self.driver.get(self.base_url)
2216 self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
2217 self.driver.find_element_by_link_text('new-default-project').click()
2218 self.driver.find_element_by_id('project-change-form-toggle').click()
2219 self.driver.find_element_by_id('project-name-change-input').clear()
2220 self.driver.find_element_by_id('project-name-change-input').send_keys('new-name')
2221 self.driver.find_element_by_id('project-name-change-btn').click()
2222 con=sqlite.connect('toaster.sqlite')
2223 cursor = con.cursor()
2224 query = "select count(name) from orm_project where name = 'new-name';"
2225 cursor.execute(query)
2226 data = cursor.fetchone()[0]
2227 self.failUnless(data == 1)
2228 #reseting project name
2229 self.driver.find_element_by_id('project-change-form-toggle').click()
2230 self.driver.find_element_by_id('project-name-change-input').clear()
2231 self.driver.find_element_by_id('project-name-change-input').send_keys('new-default-project')
2232 self.driver.find_element_by_id('project-name-change-btn').click()
2233
2234
2235 ##############
2236 # CASE 1089 #
2237 ##############
2238 def test_1089(self):
2239 self.case_no = self.get_case_number()
2240 self.log.info(' CASE %s log: ' % str(self.case_no))
2241 self.driver.maximize_window()
2242 self.driver.get(self.base_url)
2243 self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
2244 self.driver.find_element_by_link_text('new-default-project').click()
2245 self.driver.find_element_by_id('change-machine-toggle').click()
2246 self.driver.find_element_by_id('machine-change-input').clear()
2247 self.driver.find_element_by_id('machine-change-input').send_keys('qemuarm64')
2248# self.driver.find_element_by_id('machine-change-input').send_keys(Keys.RETURN)
2249 self.driver.find_element_by_id('machine-change-btn').click()
2250 con=sqlite.connect('toaster.sqlite')
2251 cursor = con.cursor()
2252 query = "select count(id) from orm_projectvariable where name like 'machine' and value like 'qemuarm64';"
2253 cursor.execute(query)
2254 data = cursor.fetchone()[0]
2255 self.failUnless(data == 1)
2256 #resetting machine to default value
2257 self.driver.find_element_by_id('change-machine-toggle').click()
2258 self.driver.find_element_by_id('machine-change-input').clear()
2259 self.driver.find_element_by_id('machine-change-input').send_keys('qemux86')
2260 self.driver.find_element_by_id('machine-change-input').send_keys(Keys.RETURN)
2261 self.driver.find_element_by_id('machine-change-btn').click()
2262
2263 ##############
2264 # CASE 1090 #
2265 ##############
2266 def test_1090(self):
2267 self.case_no = self.get_case_number()
2268 self.log.info(' CASE %s log: ' % str(self.case_no))
2269 con=sqlite.connect('toaster.sqlite')
2270 cursor = con.cursor()
2271 query = "select username from auth_user where is_superuser = 1;"
2272 cursor.execute(query)
2273 data = cursor.fetchall()
2274 try:
2275 data = data[0][0]
2276 except:
2277 pass
2278 print data
2279 self.failUnless(data == 'toaster_admin')
2280
2281 ##############
2282 # CASE 1091 #
2283 ##############
2284 def test_1091(self):
2285 self.case_no = self.get_case_number()
2286 self.log.info(' CASE %s log: ' % str(self.case_no))
2287 self.driver.maximize_window()
2288 self.driver.get(self.base_url)
2289 self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
2290 self.driver.find_element_by_link_text('new-default-project').click()
2291 self.driver.find_element_by_id('release-change-toggle').click()
2292 dropdown = self.driver.find_element_by_css_selector('select')
2293 for option in dropdown.find_elements_by_tag_name('option'):
2294 if option.text == 'Local Yocto Project':
2295 option.click()
2296 self.driver.find_element_by_id('change-release-btn').click()
2297 #wait for the changes to register in the DB
2298 time.sleep(1)
2299 con=sqlite.connect('toaster.sqlite')
2300 cursor = con.cursor()
2301 query = "select count(*) from orm_layer_version a, orm_projectlayer b, orm_project c where a.\"commit\"=\"HEAD\" and a.id = b.layercommit_id and b.project_id=c.id and c.name='new-default-project';"
2302 cursor.execute(query)
2303 data = cursor.fetchone()[0]
2304 #resetting release to default
2305 self.driver.find_element_by_id('release-change-toggle').click()
2306 dropdown = self.driver.find_element_by_css_selector('select')
2307 for option in dropdown.find_elements_by_tag_name('option'):
2308 if option.text == 'Yocto Project master':
2309 option.click()
2310 self.driver.find_element_by_id('change-release-btn').click()
2311 #wait for the changes to register in the DB
2312 time.sleep(1)
2313 self.failUnless(data == 3)
2314
2315 ##############
2316 # CASE 1092 #
2317 ##############
2318 def test_1092(self):
2319 self.case_no = self.get_case_number()
2320 self.log.info(' CASE %s log: ' % str(self.case_no))
2321 self.driver.maximize_window()
2322 con=sqlite.connect('toaster.sqlite')
2323 cursor = con.cursor()
2324 query = "select a.name, a.value from orm_projectvariable a, orm_project b where a.project_id = b.id and b.name = 'new-default-project';"
2325 cursor.execute(query)
2326 data = dict(cursor.fetchall())
2327 print data
2328 default_values = {u'IMAGE_INSTALL_append': u'', u'PACKAGE_CLASSES': u'package_rpm', u'MACHINE': u'qemux86', u'SDKMACHINE': u'x86_64', u'DISTRO': u'poky', u'IMAGE_FSTYPES': u'ext3 jffs2 tar.bz2'}
2329 self.failUnless(data == default_values)
2330
2331 ##############
2332 # CASE 1093 #
2333 ##############
2334 def test_1093(self):
2335 self.case_no = self.get_case_number()
2336 self.log.info(' CASE %s log: ' % str(self.case_no))
2337
2338 #get initial values
2339 con=sqlite.connect('toaster.sqlite')
2340 cursor = con.cursor()
2341 query = "select layercommit_id from orm_projectlayer a, orm_project b where a.project_id=b.id and b.name='new-default-project';"
2342 cursor.execute(query)
2343 data_initial = cursor.fetchall()
2344 print data_initial
2345
2346 self.driver.maximize_window()
2347 self.driver.get('localhost:8000')#self.base_url)
2348 self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
2349 self.driver.find_element_by_link_text('new-default-project').click()
2350 self.driver.find_element_by_id('release-change-toggle').click()
2351 dropdown = self.driver.find_element_by_css_selector('select')
2352 for option in dropdown.find_elements_by_tag_name('option'):
2353 if option.text == 'Local Yocto Project':
2354 option.click()
2355 self.driver.find_element_by_id('change-release-btn').click()
2356 #wait for the changes to register in the DB
2357 time.sleep(1)
2358
2359 #get changed values
2360 con=sqlite.connect('toaster.sqlite')
2361 cursor = con.cursor()
2362 query = "select layercommit_id from orm_projectlayer a, orm_project b where a.project_id=b.id and b.name='new-default-project';"
2363 cursor.execute(query)
2364 data_changed = cursor.fetchall()
2365 print data_changed
2366
2367 #resetting release to default
2368 self.driver.find_element_by_id('release-change-toggle').click()
2369 dropdown = self.driver.find_element_by_css_selector('select')
2370 for option in dropdown.find_elements_by_tag_name('option'):
2371 if option.text == 'Yocto Project master':
2372 option.click()
2373 self.driver.find_element_by_id('change-release-btn').click()
2374 #wait for the changes to register in the DB
2375 time.sleep(1)
2376 self.failUnless(data_initial != data_changed)