From 8ff7426095b03aa02a459ad33f185591fca85c08 Mon Sep 17 00:00:00 2001
From: Csók Tamás <godhak@gmail.com>
Date: Fri, 13 Mar 2015 18:14:47 +0100
Subject: [PATCH] selenium: hierachy changes, teardown clearing, method changes

---
 circle/dashboard/tests/selenium/basic_tests.py | 620 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 circle/dashboard/tests/selenium/config.py      |  55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 circle/dashboard/tests/selenium/util.py        | 548 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 668 insertions(+), 555 deletions(-)
 create mode 100644 circle/dashboard/tests/selenium/config.py
 create mode 100644 circle/dashboard/tests/selenium/util.py

diff --git a/circle/dashboard/tests/selenium/basic_tests.py b/circle/dashboard/tests/selenium/basic_tests.py
index f122950..66be58c 100644
--- a/circle/dashboard/tests/selenium/basic_tests.py
+++ b/circle/dashboard/tests/selenium/basic_tests.py
@@ -16,550 +16,58 @@
 #
 # You should have received a copy of the GNU General Public License along
 # with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.
-from selenose.cases import SeleniumTestCase
-from django.contrib.auth.models import User
+import logging
+from sys import stdout
 import random
-import urlparse
 import re
-import time
-import logging
-from selenium.webdriver.support.ui import WebDriverWait
-from selenium.webdriver.support import expected_conditions as ec
-from selenium.webdriver.support.select import Select
-from selenium.webdriver.common.by import By
-from datetime import datetime
-from selenium.common.exceptions import NoSuchElementException
-logging.getLogger(__name__)
-random_pass = "".join([random.choice(
-    '0123456789abcdefghijklmnopqrstvwxyz') for n in xrange(10)])
-random_accents = random_pass + "".join([random.choice(
-    u"áéíöóúűÁÉÍÖÓÜÚŰ") for n in xrange(5)])
-wait_max_sec = 10
-host = 'https:127.0.0.1'
-client_name = 'test_%s' % random_accents
-
-
-class UtilityMixin(object):
-    def login(self, username, password='password', location=None):
-        driver = self.driver
-        if location is None:
-            location = '/dashboard/'
-        driver.get('%s%s' % (host, location))
-        #  Only if we aren't logged in already
-        if location not in urlparse.urlparse(self.driver.current_url).path:
-            try:
-                name_input = driver.find_element_by_id("id_username")
-                password_input = driver.find_element_by_id("id_password")
-                submit_input = driver.find_element_by_id("submit-id-submit")
-            except:
-                inputs = driver.find_elements_by_tag_name("input")
-                for current_input in inputs:
-                    input_type = current_input.get_attribute("type")
-                    if input_type == "text":
-                        name_input = current_input
-                    if input_type == "password":
-                        password_input = current_input
-                    if input_type == "submit":
-                        submit_input = current_input
-            try:
-                name_input.clear()
-                name_input.send_keys(username)
-                password_input.clear()
-                password_input.send_keys(password)
-                submit_input.click()
-                try:
-                    # If selenium runs only in a small (virtual) screen
-                    driver.find_element_by_class_name('navbar-toggle').click()
-                    WebDriverWait(self.driver, wait_max_sec).until(
-                        ec.element_to_be_clickable((
-                            By.CSS_SELECTOR,
-                            "a[href*='/dashboard/profile/']")))
-                except:
-                    time.sleep(0.5)
-            except:
-                logging.exception('Selenium cannot find the form controls')
-
-    def list_options(self, select):
-        try:
-            option_dic = {}
-            select = Select(select)
-            for option in select.options:
-                key = option.get_attribute('value')
-                if key is not None and key:
-                    option_dic[key] = [option.text]
-            return option_dic
-        except:
-            logging.exception(
-                'Selenium cannot list the select possibilities')
-
-    def select_option(self, select, what=None):
-        """
-        From an HTML select imput type try to choose the specified one.
-        Select is a selenium web element type. What represent both the
-        text of the option and it's ID.
-        """
-        try:
-            my_choice = None
-            options = self.list_options(select)
-            select = Select(select)
-            if what is not None:
-                for key, value in options.iteritems():
-                    if what in key:
-                        my_choice = key
-                    else:
-                        if isinstance(value, list):
-                            for single_value in value:
-                                if what in single_value:
-                                    my_choice = key
-                        else:
-                            if what in value:
-                                my_choice = key
-            if my_choice is None:
-                my_choose_list = options.keys()
-                my_choice = my_choose_list[random.randint(
-                    0, len(my_choose_list) - 1)]
-            select.select_by_value(my_choice)
-        except:
-            logging.exception(
-                'Selenium cannot select the chosen one')
-
-    def get_link_by_href(self, target_href, attributes=None):
-        try:
-            links = self.driver.find_elements_by_tag_name('a')
-            for link in links:
-                href = link.get_attribute('href')
-                if href is not None and href:
-                    if target_href in href:
-                        perfect_fit = True
-                        if isinstance(attributes, dict):
-                            for key, target_value in attributes.iteritems():
-                                attr_check = link.get_attribute(key)
-                                if attr_check is not None and attr_check:
-                                    if target_value not in attr_check:
-                                        perfect_fit = False
-                        if perfect_fit:
-                            return link
-        except:
-            logging.exception(
-                'Selenium cannot find the href=%s link' % target_href)
-
-    def click_on_link(self, link):
-        """
-        There are situations when selenium built in click() function
-        doesn't work as intended, that's when this function is used.
-        Fires a click event via javascript injection.
-        """
-        try:
-            # Javascript function to simulate a click on a link
-            javascript = (
-                "var link = arguments[0];"
-                "var cancelled = false;"
-                "if(document.createEvent) {"
-                "   var event = document.createEvent(\"MouseEvents\");"
-                "   event.initMouseEvent("
-                "       \"click\", true, true, window, 0, 0, 0, 0, 0,"
-                "       false,false,false,false,0,null);"
-                "   cancelled = !link.dispatchEvent(event);"
-                "} else if(link.fireEvent) {"
-                "   cancelled = !link.fireEvent(\"onclick\");"
-                "} if (!cancelled) {"
-                "   window.location = link.href;"
-                "}")
-            self.driver.execute_script(javascript, link)
-        except:
-            logging.exception(
-                'Selenium cannot inject javascript to the page')
-
-    def wait_and_accept_operation(self, argument=None):
-        """
-        Accepts the operation confirmation pop up window.
-        Fills out the text inputs before accepting if argument is given.
-        """
-        try:
-            accept = WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CLASS_NAME, "modal-accept")))
-            if argument is not None:
-                possible = self.driver.find_elements_by_css_selector(
-                    "div.controls > input[type='text']")
-                if isinstance(argument, list):
-                    for x in range(0, len(possible)):
-                        possible[x].clear()
-                        possible[x].send_keys(argument[x % len(argument)])
-                else:
-                    for form in possible:
-                        form.clear()
-                        form.send_keys(argument)
-            accept.click()
-        except:
-            logging.exception(
-                'Selenium cannot accept the operation confirmation')
-
-    def save_template_from_vm(self, name):
-        try:
-            WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CSS_SELECTOR,
-                    "a[href$='/op/deploy/']")))
-            self.click_on_link(self.get_link_by_href("/op/deploy/"))
-            self.wait_and_accept_operation()
-            recent_deploy = self.recently(self.get_timeline_elements(
-                "vm.Instance.deploy"))
-            if not self.check_operation_result(recent_deploy):
-                print ("Selenium cannot deploy the "
-                       "chosen template virtual machine")
-                logging.exception('Cannot deploy the virtual machine')
-            self.click_on_link(WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CSS_SELECTOR,
-                    "a[href$='/op/shut_off/']"))))
-            self.wait_and_accept_operation()
-            recent_shut_off = self.recently(self.get_timeline_elements(
-                "vm.Instance.shut_off"))
-            if not self.check_operation_result(recent_shut_off):
-                print ("Selenium cannot shut off the "
-                       "chosen template virtual machine")
-                logging.exception('Cannot shut off the virtual machine')
-            self.click_on_link(WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CSS_SELECTOR,
-                    "a[href$='/op/save_as_template/']"))))
-            self.wait_and_accept_operation(name)
-            return name
-        except:
-            logging.exception(
-                'Selenium cannot save a vm as a template')
-
-    def create_base_template(self, name=None, architecture="x86-64",
-                             method=None, op_system=None, lease=None,
-                             network="vm"):
-        if name is None:
-            name = "template_new_%s" % client_name
-        if op_system is None:
-            op_system = "!os %s" % client_name
-        try:
-            self.driver.get('%s/dashboard/template/choose/' % host)
-            self.driver.find_element_by_css_selector(
-                "input[type='radio'][value='base_vm']").click()
-            self.driver.find_element_by_id(
-                "template-choose-next-button").click()
-            template_name = WebDriverWait(self.driver, wait_max_sec).until(
-                ec.visibility_of_element_located((
-                    By.ID, 'id_name')))
-            template_name.clear()
-            template_name.send_keys(name)
-            self.select_option(self.driver.find_element_by_id(
-                "id_arch"), architecture)
-            self.select_option(self.driver.find_element_by_id(
-                "id_access_method"), method)
-            system_name = self.driver.find_element_by_id("id_system")
-            system_name.clear()
-            system_name.send_keys(op_system)
-            self.select_option(self.driver.find_element_by_id(
-                "id_lease"), lease)
-            self.select_option(self.driver.find_element_by_id(
-                "id_networks"), network)
-            self.driver.find_element_by_css_selector(
-                "input.btn[type='submit']").click()
-            return self.save_template_from_vm(name)
-        except:
-            logging.exception(
-                'Selenium cannot create a base template virtual machine')
-
-    def get_template_id(self, name=None, from_all=False):
-        """
-        In default settings find all templates ID in the template list.
-        If name is specified searches that specific template's ID
-        from_all sets whether to use owned templates or all of them
-        Returns list of the templates ID
-        """
-        try:
-            self.driver.get('%s/dashboard/template/list/' % host)
-            css_selector_of_a_template = ("a[data-original-title]"
-                                          "[href*='/dashboard/template/']")
-            if from_all:
-                self.select_option(self.driver.find_element_by_id(
-                    'id_stype'), "all")
-                self.driver.find_element_by_css_selector(
-                    "button[type='submit']").click()
-                try:
-                    WebDriverWait(self.driver, wait_max_sec).until(
-                        ec.presence_of_element_located((
-                            By.CSS_SELECTOR, css_selector_of_a_template)))
-                except:
-                    print "Selenium could not locate any templates"
-            template_table = self.driver.find_element_by_css_selector(
-                "table[class*='template-list-table']")
-            templates = template_table.find_elements_by_css_selector("td.name")
-            found_template_ids = []
-            for template in templates:
-                if name is None or name in template.text:
-                    try:
-                        template_link = template.find_element_by_css_selector(
-                            css_selector_of_a_template)
-                        template_id = re.search(
-                            r'\d+',
-                            template_link.get_attribute("outerHTML")).group()
-                        found_template_ids.append(template_id)
-                        print ("Found '%(name)s' template's ID as %(id)s" % {
-                            'name': template.text,
-                            'id': template_id})
-                    except NoSuchElementException:
-                        pass
-                    except:
-                        raise
-            if not found_template_ids and name is not None:
-                print ("Selenium could not find the specified "
-                       "%(name)s template in the list" % {
-                           'name': name})
-            return found_template_ids
-        except:
-            logging.exception(
-                'Selenium cannot found the template\'s id')
-
-    def check_operation_result(self, operation_id, restore=True):
-        """
-        Returns wheter the operation_id result is success (returns: boolean)
-        """
-        try:
-            if restore:
-                url_base = urlparse.urlparse(self.driver.current_url)
-                url_save = ("%(host)s%(url)s" % {
-                    'host': host,
-                    'url': urlparse.urljoin(url_base.path, url_base.query)})
-                if url_base.fragment:
-                    url_save = ("%(url)s#%(fragment)s" % {
-                        'url': url_save,
-                        'fragment': url_base.fragment})
-            self.driver.get('%(host)s/dashboard/vm/activity/%(id)s/' % {
-                'host': host,
-                'id': operation_id})
-            result = WebDriverWait(self.driver, wait_max_sec).until(
-                ec.visibility_of_element_located((
-                    By.ID, "activity_status")))
-            print ("%(id)s result text is '%(result)s'" % {
-                'id': operation_id,
-                'result': result.text})
-            if (result.text == "success"):
-                out = True
-            elif (result.text == "wait"):
-                time.sleep(2)
-                out = self.check_operation_result(operation_id, False)
-            else:
-                out = False
-            if restore:
-                print "Restoring to %s url" % url_save
-                self.driver.get(url_save)
-            return out
-        except:
-            logging.exception(
-                'Selenium cannot check the result of an operation')
-
-    def recently(self, timeline_dict, second=90):
-        try:
-            if isinstance(timeline_dict, dict):
-                for key, value in timeline_dict.iteritems():
-                    time = datetime.strptime(key, '%Y-%m-%d %H:%M')
-                    delta = datetime.now() - time
-                    if delta.total_seconds() <= second:
-                        return value
-        except:
-            logging.exception(
-                'Selenium cannot filter timeline activities to recent')
-
-    def get_timeline_elements(self, code=None):
-        try:
-            if code is None:
-                css_activity_selector = "div[data-activity-code]"
-                code = "all activity"
-            else:
-                css_activity_selector = ("div[data-activity-code="
-                                         "'%(code)s']" % {
-                                             'code': code})
-            WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CSS_SELECTOR, "a[href*='#activity']"))).click()
-            activity_dict = {}
-            timeline = WebDriverWait(self.driver, wait_max_sec).until(
-                ec.visibility_of_element_located((
-                    By.ID, "activity-timeline")))
-            searched_activity = timeline.find_elements_by_css_selector(
-                css_activity_selector)
-            print "Found activity list for %s:" % code
-            for activity in searched_activity:
-                activity_id = activity.get_attribute('data-activity-id')
-                activity_text = activity.text
-                key = re.search(
-                    r'\d+-\d+-\d+ \d+:\d+,', activity_text).group()[:-1]
-                print ("%(id)s @ %(activity)s" % {
-                    'id': activity_id,
-                    'activity': key})
-                activity_dict[key] = activity_id
-            return activity_dict
-        except:
-            logging.exception('Selenium cannot find the searched activity')
-
-    def create_template_from_base(self, delete_disk=True, name=None):
-        try:
-            if name is None:
-                name = "template_from_base_%s" % client_name
-            self.driver.get('%s/dashboard/template/choose/' % host)
-            choice_list = []
-            choices = self.driver.find_elements_by_css_selector(
-                "input[type='radio']")
-            choice_list = [item for item in choices if (
-                'test' not in item.get_attribute('value')
-                and item.get_attribute('value') != 'base_vm')]
-            chosen = random.randint(0, len(choice_list) - 1)
-            choice_list[chosen].click()
-            self.driver.find_element_by_id(
-                "template-choose-next-button").click()
-            if delete_disk:
-                self.click_on_link(
-                    self.get_link_by_href("#resources"))
-                disks = WebDriverWait(self.driver, wait_max_sec).until(
-                    ec.visibility_of_element_located((
-                        By.ID, 'vm-details-resources-disk')))
-                disk_list = disks.find_elements_by_css_selector(
-                    "h4[class*='list-group-item-heading']")
-                if len(disk_list) > 0:
-                    self.click_on_link(
-                        self.get_link_by_href("/op/remove_disk/"))
-                    self.wait_and_accept_operation()
-                    WebDriverWait(self.driver, wait_max_sec).until(
-                        ec.visibility_of_element_located((
-                            By.ID, "_activity")))
-                    recent_remove_disk = self.recently(
-                        self.get_timeline_elements(
-                            "vm.Instance.remove_disk"))
-                    if not self.check_operation_result(recent_remove_disk):
-                        print ("Selenium cannot delete disk "
-                               "of the chosen template")
-                        logging.exception('Cannot delete disk')
-                return self.save_template_from_vm(name)
-        except:
-            logging.exception(
-                'Selenium cannot start a template from a base one')
+import urlparse
 
-    def delete_template(self, template_id):
-        try:
-            self.driver.get('%s/dashboard/template/%s/' % (host, template_id))
-            url = urlparse.urlparse(self.driver.current_url)
-            self.click_on_link(
-                self.get_link_by_href(
-                    "/dashboard/template/delete/%s/" % template_id))
-            self.wait_and_accept_operation()
-            WebDriverWait(self.driver, wait_max_sec).until(
-                ec.visibility_of_element_located((
-                    By.CLASS_NAME, 'alert-success')))
-            url = urlparse.urlparse(self.driver.current_url)
-            if "/template/list/" not in url.path:
-                logging.exception(
-                    'System does not redirect to template listing')
-        except:
-            logging.exception('Selenium cannot delete the desired template')
+from django.contrib.auth.models import User
+from django.db.models import Q
 
-    def create_random_vm(self):
-        try:
-            self.driver.get('%s/dashboard/vm/create/' % host)
-            vm_list = []
-            pk = None
-            vm_list = self.driver.find_elements_by_class_name(
-                'vm-create-template-summary')
-            choice = random.randint(0, len(vm_list) - 1)
-            vm_list[choice].click()
-            WebDriverWait(self.driver, wait_max_sec).until(
-                ec.element_to_be_clickable((
-                    By.CLASS_NAME, 'vm-create-start'))).click()
-            WebDriverWait(self.driver, wait_max_sec).until(
-                ec.visibility_of_element_located((
-                    By.CLASS_NAME, 'alert-success')))
-            url = urlparse.urlparse(self.driver.current_url)
-            pk = re.search(r'\d+', url.path).group()
-            return pk
-        except:
-            logging.exception('Selenium cannot start a VM')
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as ec
+from selenium.webdriver.support.ui import WebDriverWait
+from selenose.cases import SeleniumTestCase
 
-    def view_change(self, target_box):
-        driver = self.driver
-        driver.get('%s/dashboard/' % host)
-        list_view = driver.find_element_by_id('%s-list-view' % target_box)
-        graph_view = driver.find_element_by_id('%s-graph-view' % target_box)
-        js_script = 'return arguments[0].style.display;'
-        required_attributes = {'data-index-box': target_box}
-        graph_view_link = self.get_link_by_href(
-            '#index-graph-view',
-            required_attributes).find_element_by_tag_name('i')
-        list_view_link = self.get_link_by_href(
-            '#index-list-view',
-            required_attributes).find_element_by_tag_name('i')
-        self.click_on_link(list_view_link)
-        states = [driver.execute_script(js_script, list_view),
-                  driver.execute_script(js_script, graph_view)]
-        self.click_on_link(graph_view_link)
-        states.extend([driver.execute_script(js_script, list_view),
-                       driver.execute_script(js_script, graph_view)])
-        self.click_on_link(list_view_link)
-        states.extend([driver.execute_script(js_script, list_view),
-                       driver.execute_script(js_script, graph_view)])
-        return states
+from vm.models import Instance
+from .config import SeleniumConfig
+from .util import CircleSeleniumMixin, SeleniumMixin
 
-    def delete_vm(self, pk):
-        try:
-            # For relability reasons instead of using the JS operatation
-            self.driver.get("%(host)s/dashboard/vm/%(id)s/op/destroy/" % {
-                'host': host,
-                'id': pk})
-            self.wait_and_accept_operation()
-            try:
-                status_span = WebDriverWait(self.driver, wait_max_sec).until(
-                    ec.visibility_of_element_located((
-                        By.ID, 'vm-details-state')))
-                WebDriverWait(status_span, wait_max_sec).until(
-                    ec.visibility_of_element_located((
-                        By.CLASS_NAME, 'fa-trash-o')))
-            except:
-                # Selenium can time-out by not realising the JS refresh
-                recent_destroy_vm = self.recently(
-                    self.get_timeline_elements("vm.Instance.destroy"))
-                if not self.check_operation_result(recent_destroy_vm):
-                    print ("Selenium cannot destroy "
-                           "the chosen %(id)s vm" % {
-                               'id': pk})
-                    logging.exception('Cannot destroy the specified vm')
-            self.driver.get('%s/dashboard/vm/%s/' % (host, pk))
-            try:
-                WebDriverWait(self.driver, wait_max_sec).until(
-                    ec.visibility_of_element_located((
-                        By.CSS_SELECTOR,
-                        "span[data-status*='DESTROYED']")))
-                return True
-            except:
-                return False
-        except:
-            logging.exception("Selenium can not destroy a VM")
+logger = logging.getLogger(__name__)
+consoleHandler = logging.StreamHandler(stdout)
+logger.addHandler(consoleHandler)
+conf = SeleniumConfig()
 
 
-class VmDetailTest(UtilityMixin, SeleniumTestCase):
-    template_ids = []
-    vm_ids = []
+class BasicSeleniumTests(SeleniumTestCase, SeleniumMixin, CircleSeleniumMixin):
+    def __init__(self, *args, **kwargs):
+        super(self.__class__, self).__init__(*args, **kwargs)
+        self.conf = conf
+        self.template_ids = []
+        self.vm_ids = []
 
     @classmethod
     def setup_class(cls):
-        cls._user = User.objects.create(username=client_name,
-                                        is_superuser=True)
-        cls._user.set_password(random_accents)
-        cls._user.save()
+        if conf.create_user:
+            cls._user = User.objects.create(username=conf.client_name,
+                                            is_superuser=True)
+            cls._user.set_password(conf.random_pass)
+            cls._user.save()
 
     @classmethod
     def teardown_class(cls):
-        cls._user.delete()
+        if conf.create_user:
+            for instance in Instance.objects.all().filter(
+                    ~Q(status=u'DESTROYED'), owner=cls._user):
+                instance.destroy(system=True)
+            cls._user.delete()
 
     def test_01_login(self):
         title = 'Dashboard | CIRCLE'
         location = '/dashboard/'
-        self.login(client_name, random_accents)
-        self.driver.get('%s/dashboard/' % host)
+        self.login()
+        self.driver.get('%s/dashboard/' % conf.host)
         url = urlparse.urlparse(self.driver.current_url)
         (self.assertIn('%s' % title, self.driver.title,
                        '%s is not found in the title' % title) or
@@ -567,17 +75,17 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
                              'URL path is not equal with %s' % location))
 
     def test_02_add_template_rights(self):
-        self.login(client_name, random_accents)
+        self.login()
         template_pool = self.get_template_id(from_all=True)
         if len(template_pool) > 1:
             chosen = template_pool[random.randint(0, len(template_pool) - 1)]
         elif len(template_pool) == 1:
             chosen = template_pool[0]
         else:
-            print "Selenium did not found any templates"
+            logging.warning("Selenium did not found any templates")
             logging.exception(
                 "System did not meet required conditions to continue")
-        self.driver.get('%s/dashboard/template/%s/' % (host, chosen))
+        self.driver.get('%s/dashboard/template/%s/' % (conf.host, chosen))
         acces_form = self.driver.find_element_by_css_selector(
             "form[action*='/dashboard/template/%(template_id)s/acl/']"
             "[method='post']" % {
@@ -587,8 +95,8 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
         user_status = acces_form.find_element_by_css_selector(
             "select[name='level']")
         user_name.clear()
-        user_name.send_keys(client_name)
-        self.select_option(user_status)
+        user_name.send_keys(conf.client_name)
+        self.select_option(user_status, 'user')
         # For strange reasons clicking on submit button doesn't work anymore
         acces_form.submit()
         found_users = []
@@ -598,31 +106,33 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
             user_text = re.split(r':[ ]?', user.text)
             if len(user_text) == 2:
                 found_name = re.search(r'[\w\W]+(?=\))', user_text[1]).group()
-                print ("'%(user)s' found in ACL list for template %(id)s" % {
-                    'user': found_name,
-                    'id': chosen})
+                logging.info("'%(user)s' found in ACL "
+                             "list for template %(id)s" % {
+                                 'user': found_name,
+                                 'id': chosen})
                 found_users.append(found_name)
-        self.assertIn(client_name, found_users,
+        self.assertIn(conf.client_name, found_users,
                       "Could not add user to template's ACL")
 
     def test_03_able_to_create_template(self):
-        self.login(client_name, random_accents)
+        self.login()
         template_list = None
         create_template = self.get_link_by_href('/dashboard/template/choose/')
         self.click_on_link(create_template)
-        WebDriverWait(self.driver, wait_max_sec).until(
+        WebDriverWait(self.driver, conf.wait_max_sec).until(
             ec.visibility_of_element_located((
                 By.ID, 'confirmation-modal')))
         template_list = self.driver.find_elements_by_class_name(
             'template-choose-list-element')
-        print 'Selenium found %s template possibilities' % len(template_list)
+        logging.info('Selenium found %(count)s template possibilities' % {
+            'count': len(template_list)})
         (self.assertIsNotNone(
             template_list, "Selenium can not find the create template list") or
             self.assertGreater(len(template_list), 0,
                                "The create template list is empty"))
 
     def test_04_create_base_template(self):
-        self.login(client_name, random_accents)
+        self.login()
         created_template_id = self.get_template_id(
             self.create_base_template())
         found = created_template_id is not None
@@ -633,7 +143,7 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
             "Could not found the created template in the template list")
 
     def test_05_create_template_from_base(self):
-        self.login(client_name, random_accents)
+        self.login()
         created_template_id = self.get_template_id(
             self.create_template_from_base())
         found = created_template_id is not None
@@ -645,9 +155,9 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
 
     def test_06_delete_templates(self):
         success = False
-        self.login(client_name, random_accents)
+        self.login()
         for template_id in self.template_ids:
-            print "Deleting template %s" % template_id
+            logging.info("Deleting template %s" % template_id)
             self.delete_template(template_id)
         existing_templates = self.get_template_id()
         if len(existing_templates) == 0:
@@ -662,52 +172,52 @@ class VmDetailTest(UtilityMixin, SeleniumTestCase):
             success, "Could not delete (all) the test template(s)")
 
     def test_07_able_to_create_vm(self):
-        self.login(client_name, random_accents)
+        self.login()
         vm_list = None
         create_vm_link = self.get_link_by_href('/dashboard/vm/create/')
         create_vm_link.click()
-        WebDriverWait(self.driver, wait_max_sec).until(
+        WebDriverWait(self.driver, conf.wait_max_sec).until(
             ec.visibility_of_element_located((
                 By.ID, 'confirmation-modal')))
         vm_list = self.driver.find_elements_by_class_name(
             'vm-create-template-summary')
-        print ("Selenium found %(vm_number)s virtual machine template "
-               " possibilities" % {
-                   'vm_number': len(vm_list)})
+        logging.info("Selenium found %(vm_number)s virtual machine template "
+                     " possibilities" % {
+                         'vm_number': len(vm_list)})
         (self.assertIsNotNone(
             vm_list, "Selenium can not find the VM list") or
             self.assertGreater(len(vm_list), 0, "The create VM list is empty"))
 
     def test_08_create_vm(self):
-        self.login(client_name, random_accents)
+        self.login()
         pk = self.create_random_vm()
         self.vm_ids.append(pk)
         self.assertIsNotNone(pk, "Can not create a VM")
 
     def test_09_vm_view_change(self):
-        self.login(client_name, random_accents)
+        self.login()
         expected_states = ["", "none",
                            "none", "",
                            "block", "none"]
         states = self.view_change("vm")
-        print 'states: [%s]' % ', '.join(map(str, states))
-        print 'expected: [%s]' % ', '.join(map(str, expected_states))
+        logging.info('states: [%s]' % ', '.join(map(str, states)))
+        logging.info('expected: [%s]' % ', '.join(map(str, expected_states)))
         self.assertListEqual(states, expected_states,
                              "The view mode does not change for VM listing")
 
     def test_10_node_view_change(self):
-        self.login(client_name, random_accents)
+        self.login()
         expected_states = ["", "none",
                            "none", "",
                            "block", "none"]
         states = self.view_change("node")
-        print 'states: [%s]' % ', '.join(map(str, states))
-        print 'expected: [%s]' % ', '.join(map(str, expected_states))
+        logging.info('states: [%s]' % ', '.join(map(str, states)))
+        logging.info('expected: [%s]' % ', '.join(map(str, expected_states)))
         self.assertListEqual(states, expected_states,
                              "The view mode does not change for NODE listing")
 
     def test_11_delete_vm(self):
-        self.login(client_name, random_accents)
+        self.login()
         succes = True
         for vm in self.vm_ids:
             if not self.delete_vm(vm):
diff --git a/circle/dashboard/tests/selenium/config.py b/circle/dashboard/tests/selenium/config.py
new file mode 100644
index 0000000..37bcdb8
--- /dev/null
+++ b/circle/dashboard/tests/selenium/config.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Budapest University of Technology and Economics (BME IK)
+#
+# This file is part of CIRCLE Cloud.
+#
+# CIRCLE is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along
+# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.
+import random
+
+
+class SeleniumConfig:
+    # How many sec can selenium wait till certain parts of a page appears
+    wait_max_sec = 10
+    # How much sec can pass before the activity is no longer happened recently
+    recently_sec = 90
+
+    # Accented letters from which selenium can choose to name stuff
+    accents = u"áéíöóúűÁÉÍÖÓÜÚŰ"
+    # Non accented letters from which selenium can choose to name stuff
+    valid_chars = "0123456789abcdefghijklmnopqrstvwxyz"
+
+    # First we choose 10 random normal letters
+    random_pass = "".join([random.choice(
+        valid_chars) for n in xrange(10)])
+    # Then we append it with 5 random accented one
+    random_pass += "".join([random.choice(
+        accents) for n in xrange(5)])
+    # Then we name our client as test_%(password)s
+    client_name = 'test_%s' % random_pass
+
+    # Which webpage should selenium use (localhost is recommended)
+    host = 'https:127.0.0.1'
+    # In default the tests create a new user then delete it afteword
+    # Disable this if selenium cannot acces the database
+    create_user = True
+
+    """
+    Note: It's possible to setup that selenium uses a distant web server
+    for testing. If you choose this method you must provide a distant superuser
+    account info for that server by overriding random_pass and client_name by
+    uncommenting the lines below.
+    """
+    # client_name = "user name here"
+    # random_pass = "password here"
diff --git a/circle/dashboard/tests/selenium/util.py b/circle/dashboard/tests/selenium/util.py
new file mode 100644
index 0000000..cdd8bee
--- /dev/null
+++ b/circle/dashboard/tests/selenium/util.py
@@ -0,0 +1,548 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright 2014 Budapest University of Technology and Economics (BME IK)
+#
+# This file is part of CIRCLE Cloud.
+#
+# CIRCLE is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along
+# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.
+from datetime import datetime
+import logging
+from sys import stdout
+import random
+import re
+import time
+import urlparse
+
+from selenium.common.exceptions import NoSuchElementException
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as ec
+from selenium.webdriver.support.select import Select
+from selenium.webdriver.support.ui import WebDriverWait
+
+logger = logging.getLogger(__name__)
+consoleHandler = logging.StreamHandler(stdout)
+logger.addHandler(consoleHandler)
+
+
+class CircleSeleniumMixin(object):
+    def login(self, location=None):
+        driver = self.driver
+        if location is None:
+            location = '/dashboard/'
+        driver.get('%s%s' % (self.conf.host, location))
+        #  Only if we aren't logged in already
+        if location not in urlparse.urlparse(self.driver.current_url).path:
+            try:
+                name_input = driver.find_element_by_id("id_username")
+                password_input = driver.find_element_by_id("id_password")
+                submit_input = driver.find_element_by_id("submit-id-submit")
+            except:
+                inputs = driver.find_elements_by_tag_name("input")
+                for current_input in inputs:
+                    input_type = current_input.get_attribute("type")
+                    if input_type == "text":
+                        name_input = current_input
+                    if input_type == "password":
+                        password_input = current_input
+                    if input_type == "submit":
+                        submit_input = current_input
+            try:
+                name_input.clear()
+                name_input.send_keys(self.conf.client_name)
+                password_input.clear()
+                password_input.send_keys(self.conf.random_pass)
+                submit_input.click()
+                try:
+                    # If selenium runs only in a small (virtual) screen
+                    driver.find_element_by_class_name('navbar-toggle').click()
+                    WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                        ec.element_to_be_clickable((
+                            By.CSS_SELECTOR,
+                            "a[href*='/dashboard/profile/']")))
+                except:
+                    time.sleep(0.5)
+            except:
+                logging.exception('Selenium cannot find the form controls')
+
+    def wait_and_accept_operation(self, argument=None):
+        """
+        Accepts the operation confirmation pop up window.
+        Fills out the text inputs before accepting if argument is given.
+        """
+        try:
+            accept = WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.element_to_be_clickable((
+                    By.CLASS_NAME, "modal-accept")))
+            if argument is not None:
+                possible = self.driver.find_elements_by_css_selector(
+                    "div.controls > input[type='text']")
+                if isinstance(argument, list):
+                    for x in range(0, len(possible)):
+                        possible[x].clear()
+                        possible[x].send_keys(argument[x % len(argument)])
+                else:
+                    for form in possible:
+                        form.clear()
+                        form.send_keys(argument)
+            accept.click()
+        except:
+            logging.exception(
+                'Selenium cannot accept the operation confirmation')
+
+    def save_template_from_vm(self, name):
+        try:
+            WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.element_to_be_clickable((
+                    By.CSS_SELECTOR,
+                    "a[href$='/op/deploy/']")))
+            self.click_on_link(self.get_link_by_href("/op/deploy/"))
+            self.wait_and_accept_operation()
+            recent_deploy = self.recently(self.get_timeline_elements(
+                "vm.Instance.deploy"))
+            if not self.check_operation_result(recent_deploy):
+                logging.warning("Selenium cannot deploy the "
+                                "chosen template virtual machine")
+                logging.exception('Cannot deploy the virtual machine')
+            self.click_on_link(WebDriverWait(
+                self.driver, self.conf.wait_max_sec).until(
+                    ec.element_to_be_clickable((
+                        By.CSS_SELECTOR,
+                        "a[href$='/op/shut_off/']"))))
+            self.wait_and_accept_operation()
+            recent_shut_off = self.recently(self.get_timeline_elements(
+                "vm.Instance.shut_off"))
+            if not self.check_operation_result(recent_shut_off):
+                logging.warning("Selenium cannot shut off the "
+                                "chosen template virtual machine")
+                logging.exception('Cannot shut off the virtual machine')
+            self.click_on_link(WebDriverWait(
+                self.driver, self.conf.wait_max_sec).until(
+                    ec.element_to_be_clickable((
+                        By.CSS_SELECTOR,
+                        "a[href$='/op/save_as_template/']"))))
+            self.wait_and_accept_operation(name)
+            return name
+        except:
+            logging.exception(
+                'Selenium cannot save a vm as a template')
+
+    def create_base_template(self, name=None, architecture="x86-64",
+                             method=None, op_system=None, lease=None,
+                             network="vm"):
+        if name is None:
+            name = "template_new_%s" % self.conf.client_name
+        if op_system is None:
+            op_system = "!os %s" % self.conf.client_name
+        try:
+            self.driver.get('%s/dashboard/template/choose/' % self.conf.host)
+            self.driver.find_element_by_css_selector(
+                "input[type='radio'][value='base_vm']").click()
+            self.driver.find_element_by_id(
+                "template-choose-next-button").click()
+            template_name = WebDriverWait(
+                self.driver, self.conf.wait_max_sec).until(
+                    ec.visibility_of_element_located((
+                        By.ID, 'id_name')))
+            template_name.clear()
+            template_name.send_keys(name)
+            self.select_option(self.driver.find_element_by_id(
+                "id_arch"), architecture)
+            self.select_option(self.driver.find_element_by_id(
+                "id_access_method"), method)
+            system_name = self.driver.find_element_by_id("id_system")
+            system_name.clear()
+            system_name.send_keys(op_system)
+            self.select_option(self.driver.find_element_by_id(
+                "id_lease"), lease)
+            self.select_option(self.driver.find_element_by_id(
+                "id_networks"), network)
+            self.driver.find_element_by_css_selector(
+                "input.btn[type='submit']").click()
+            return self.save_template_from_vm(name)
+        except:
+            logging.exception(
+                'Selenium cannot create a base template virtual machine')
+
+    def get_template_id(self, name=None, from_all=False):
+        """
+        In default settings find all templates ID in the template list.
+        If name is specified searches that specific template's ID
+        from_all sets whether to use owned templates or all of them
+        Returns list of the templates ID
+        """
+        try:
+            self.driver.get('%s/dashboard/template/list/' % self.conf.host)
+            css_selector_of_a_template = ("a[data-original-title]"
+                                          "[href*='/dashboard/template/']")
+            if from_all:
+                self.select_option(self.driver.find_element_by_id(
+                    'id_stype'), "all")
+                self.driver.find_element_by_css_selector(
+                    "button[type='submit']").click()
+                try:
+                    WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                        ec.presence_of_element_located((
+                            By.CSS_SELECTOR, css_selector_of_a_template)))
+                except:
+                    logging.warning("Selenium could not locate any templates")
+            template_table = self.driver.find_element_by_css_selector(
+                "table[class*='template-list-table']")
+            templates = template_table.find_elements_by_css_selector("td.name")
+            found_template_ids = []
+            for template in templates:
+                if name is None or name in template.text:
+                    try:
+                        template_link = template.find_element_by_css_selector(
+                            css_selector_of_a_template)
+                        template_id = re.search(
+                            r'\d+',
+                            template_link.get_attribute("outerHTML")).group()
+                        found_template_ids.append(template_id)
+                        logging.info("Found '%(name)s' "
+                                     "template's ID as %(id)s" % {
+                                         'name': template.text,
+                                         'id': template_id})
+                    except NoSuchElementException:
+                        pass
+                    except:
+                        raise
+            if not found_template_ids and name is not None:
+                logging.warning("Selenium could not find the specified "
+                                "%(name)s template in the list" % {
+                                    'name': name})
+            return found_template_ids
+        except:
+            logging.exception(
+                'Selenium cannot found the template\'s id')
+
+    def check_operation_result(self, operation_id, restore=True):
+        """
+        Returns wheter the operation_id result is success (returns: boolean)
+        """
+        try:
+            if restore:
+                url_base = urlparse.urlparse(self.driver.current_url)
+                url_save = ("%(host)s%(url)s" % {
+                    'host': self.conf.host,
+                    'url': urlparse.urljoin(url_base.path, url_base.query)})
+                if url_base.fragment:
+                    url_save = ("%(url)s#%(fragment)s" % {
+                        'url': url_save,
+                        'fragment': url_base.fragment})
+            self.driver.get('%(host)s/dashboard/vm/activity/%(id)s/' % {
+                'host': self.conf.host,
+                'id': operation_id})
+            result = WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.visibility_of_element_located((
+                    By.ID, "activity_status")))
+            logging.info("%(id)s result text is '%(result)s'" % {
+                'id': operation_id,
+                'result': result.text})
+            if (result.text == "success"):
+                out = True
+            elif (result.text == "wait"):
+                time.sleep(2)
+                out = self.check_operation_result(operation_id, False)
+            else:
+                out = False
+            if restore:
+                logging.info("Restoring to %s url" % url_save)
+                self.driver.get(url_save)
+            return out
+        except:
+            logging.exception(
+                'Selenium cannot check the result of an operation')
+
+    def recently(self, timeline_dict, second=None):
+        if second is None:
+            second = self.conf.recently_sec
+        try:
+            if isinstance(timeline_dict, dict):
+                for key, value in timeline_dict.iteritems():
+                    time = datetime.strptime(key, '%Y-%m-%d %H:%M')
+                    delta = datetime.now() - time
+                    if delta.total_seconds() <= second:
+                        return value
+        except:
+            logging.exception(
+                'Selenium cannot filter timeline activities to recent')
+
+    def get_timeline_elements(self, code=None):
+        try:
+            if code is None:
+                css_activity_selector = "div[data-activity-code]"
+                code = "all activity"
+            else:
+                css_activity_selector = ("div[data-activity-code="
+                                         "'%(code)s']" % {
+                                             'code': code})
+            WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.element_to_be_clickable((
+                    By.CSS_SELECTOR, "a[href*='#activity']"))).click()
+            activity_dict = {}
+            timeline = WebDriverWait(
+                self.driver, self.conf.wait_max_sec).until(
+                    ec.visibility_of_element_located((
+                        By.ID, "activity-timeline")))
+            searched_activity = timeline.find_elements_by_css_selector(
+                css_activity_selector)
+            logging.info("Found activity list for %s:" % code)
+            for activity in searched_activity:
+                activity_id = activity.get_attribute('data-activity-id')
+                activity_text = activity.text
+                key = re.search(
+                    r'\d+-\d+-\d+ \d+:\d+,', activity_text).group()[:-1]
+                logging.info("%(id)s @ %(activity)s" % {
+                    'id': activity_id,
+                    'activity': key})
+                activity_dict[key] = activity_id
+            return activity_dict
+        except:
+            logging.exception('Selenium cannot find the searched activity')
+
+    def create_template_from_base(self, delete_disk=True, name=None):
+        try:
+            if name is None:
+                name = "template_from_base_%s" % self.conf.client_name
+            self.driver.get('%s/dashboard/template/choose/' % self.conf.host)
+            choice_list = []
+            choices = self.driver.find_elements_by_css_selector(
+                "input[type='radio']")
+            choice_list = [item for item in choices if (
+                'test' not in item.get_attribute('value')
+                and item.get_attribute('value') != 'base_vm')]
+            chosen = random.randint(0, len(choice_list) - 1)
+            choice_list[chosen].click()
+            self.driver.find_element_by_id(
+                "template-choose-next-button").click()
+            if delete_disk:
+                self.click_on_link(
+                    self.get_link_by_href("#resources"))
+                disks = WebDriverWait(
+                    self.driver, self.conf.wait_max_sec).until(
+                        ec.visibility_of_element_located((
+                            By.ID, 'vm-details-resources-disk')))
+                disk_list = disks.find_elements_by_css_selector(
+                    "h4[class*='list-group-item-heading']")
+                if len(disk_list) > 0:
+                    self.click_on_link(
+                        self.get_link_by_href("/op/remove_disk/"))
+                    self.wait_and_accept_operation()
+                    WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                        ec.visibility_of_element_located((
+                            By.ID, "_activity")))
+                    recent_remove_disk = self.recently(
+                        self.get_timeline_elements(
+                            "vm.Instance.remove_disk"))
+                    if not self.check_operation_result(recent_remove_disk):
+                        logging.warning("Selenium cannot delete disk "
+                                        "of the chosen template")
+                        logging.exception('Cannot delete disk')
+                return self.save_template_from_vm(name)
+        except:
+            logging.exception(
+                'Selenium cannot start a template from a base one')
+
+    def delete_template(self, template_id):
+        try:
+            self.driver.get(
+                '%s/dashboard/template/%s/' % (self.conf.host, template_id))
+            url = urlparse.urlparse(self.driver.current_url)
+            self.click_on_link(
+                self.get_link_by_href(
+                    "/dashboard/template/delete/%s/" % template_id))
+            self.wait_and_accept_operation()
+            WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.visibility_of_element_located((
+                    By.CLASS_NAME, 'alert-success')))
+            url = urlparse.urlparse(self.driver.current_url)
+            if "/template/list/" not in url.path:
+                logging.exception(
+                    'System does not redirect to template listing')
+        except:
+            logging.exception('Selenium cannot delete the desired template')
+
+    def create_random_vm(self):
+        try:
+            self.driver.get('%s/dashboard/vm/create/' % self.conf.host)
+            vm_list = []
+            pk = None
+            vm_list = self.driver.find_elements_by_class_name(
+                'vm-create-template-summary')
+            choice = random.randint(0, len(vm_list) - 1)
+            vm_list[choice].click()
+            WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.element_to_be_clickable((
+                    By.CLASS_NAME, 'vm-create-start'))).click()
+            WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                ec.visibility_of_element_located((
+                    By.CLASS_NAME, 'alert-success')))
+            url = urlparse.urlparse(self.driver.current_url)
+            pk = re.search(r'\d+', url.path).group()
+            return pk
+        except:
+            logging.exception('Selenium cannot start a VM')
+
+    def view_change(self, target_box):
+        driver = self.driver
+        driver.get('%s/dashboard/' % self.conf.host)
+        list_view = driver.find_element_by_id('%s-list-view' % target_box)
+        graph_view = driver.find_element_by_id('%s-graph-view' % target_box)
+        js_script = 'return arguments[0].style.display;'
+        required_attributes = {'data-index-box': target_box}
+        graph_view_link = self.get_link_by_href(
+            '#index-graph-view',
+            required_attributes).find_element_by_tag_name('i')
+        list_view_link = self.get_link_by_href(
+            '#index-list-view',
+            required_attributes).find_element_by_tag_name('i')
+        self.click_on_link(list_view_link)
+        states = [driver.execute_script(js_script, list_view),
+                  driver.execute_script(js_script, graph_view)]
+        self.click_on_link(graph_view_link)
+        states.extend([driver.execute_script(js_script, list_view),
+                       driver.execute_script(js_script, graph_view)])
+        self.click_on_link(list_view_link)
+        states.extend([driver.execute_script(js_script, list_view),
+                       driver.execute_script(js_script, graph_view)])
+        return states
+
+    def delete_vm(self, pk):
+        try:
+            # For relability reasons instead of using the JS operatation
+            self.driver.get("%(host)s/dashboard/vm/%(id)s/op/destroy/" % {
+                'host': self.conf.host,
+                'id': pk})
+            self.wait_and_accept_operation()
+            try:
+                status_span = WebDriverWait(
+                    self.driver, self.conf.wait_max_sec).until(
+                        ec.visibility_of_element_located((
+                            By.ID, 'vm-details-state')))
+                WebDriverWait(status_span, self.conf.wait_max_sec).until(
+                    ec.visibility_of_element_located((
+                        By.CLASS_NAME, 'fa-trash-o')))
+            except:
+                # Selenium can time-out by not realising the JS refresh
+                recent_destroy_vm = self.recently(
+                    self.get_timeline_elements("vm.Instance.destroy"))
+                if not self.check_operation_result(recent_destroy_vm):
+                    logging.warning("Selenium cannot destroy "
+                                    "the chosen %(id)s vm" % {
+                                        'id': pk})
+                    logging.exception('Cannot destroy the specified vm')
+            self.driver.get('%s/dashboard/vm/%s/' % (self.conf.host, pk))
+            try:
+                WebDriverWait(self.driver, self.conf.wait_max_sec).until(
+                    ec.visibility_of_element_located((
+                        By.CSS_SELECTOR,
+                        "span[data-status*='DESTROYED']")))
+                return True
+            except:
+                return False
+        except:
+            logging.exception("Selenium can not destroy a VM")
+
+
+class SeleniumMixin(object):
+    def list_options(self, select):
+        try:
+            option_dic = {}
+            select = Select(select)
+            for option in select.options:
+                key = option.get_attribute('value')
+                if key is not None and key:
+                    option_dic[key] = [option.text]
+            return option_dic
+        except:
+            logging.exception(
+                'Selenium cannot list the select possibilities')
+
+    def select_option(self, select, what=None):
+        """
+        From an HTML select imput type try to choose the specified one.
+        Select is a selenium web element type. What represent both the
+        text of the option and it's ID.
+        """
+        try:
+            my_choice = None
+            options = self.list_options(select)
+            select = Select(select)
+            if what is not None:
+                for key, value in options.iteritems():
+                    if what in key:
+                        my_choice = key
+                    else:
+                        if isinstance(value, list):
+                            for single_value in value:
+                                if what in single_value:
+                                    my_choice = key
+                        else:
+                            if what in value:
+                                my_choice = key
+            if my_choice is None:
+                my_choose_list = options.keys()
+                my_choice = my_choose_list[random.randint(
+                    0, len(my_choose_list) - 1)]
+            select.select_by_value(my_choice)
+        except:
+            logging.exception(
+                'Selenium cannot select the chosen one')
+
+    def get_link_by_href(self, target_href, attributes=None):
+        try:
+            links = self.driver.find_elements_by_tag_name('a')
+            for link in links:
+                href = link.get_attribute('href')
+                if href is not None and href:
+                    if target_href in href:
+                        perfect_fit = True
+                        if isinstance(attributes, dict):
+                            for key, target_value in attributes.iteritems():
+                                attr_check = link.get_attribute(key)
+                                if attr_check is not None and attr_check:
+                                    if target_value not in attr_check:
+                                        perfect_fit = False
+                        if perfect_fit:
+                            return link
+        except:
+            logging.exception(
+                'Selenium cannot find the href=%s link' % target_href)
+
+    def click_on_link(self, link):
+        """
+        There are situations when selenium built in click() function
+        doesn't work as intended, that's when this function is used.
+        Fires a click event via javascript injection.
+        """
+        try:
+            # Javascript function to simulate a click on a link
+            javascript = (
+                "var link = arguments[0];"
+                "var cancelled = false;"
+                "if(document.createEvent) {"
+                "   var event = document.createEvent(\"MouseEvents\");"
+                "   event.initMouseEvent("
+                "       \"click\", true, true, window, 0, 0, 0, 0, 0,"
+                "       false,false,false,false,0,null);"
+                "   cancelled = !link.dispatchEvent(event);"
+                "} else if(link.fireEvent) {"
+                "   cancelled = !link.fireEvent(\"onclick\");"
+                "} if (!cancelled) {"
+                "   window.location = link.href;"
+                "}")
+            self.driver.execute_script(javascript, link)
+        except:
+            logging.exception(
+                'Selenium cannot inject javascript to the page')
--
libgit2 0.26.0