示例#1
0
 def click_on_saved_reports(self):
     self.accordion.accordion_by_name("Saved Reports").click()
     self._wait_for_results_refresh()
     from cfme.web_ui import Tree
     tree = Tree("//tr[@title='All Saved Reports']/../..")
     tree.click_path("All Saved Reports")
     return VirtualIntelligence.SavedReportsSection(self.testsetup)
 def click_on_saved_reports(self):
     self.accordion.accordion_by_name("Saved Reports").click()
     self._wait_for_results_refresh()
     from cfme.web_ui import Tree
     tree = Tree("//tr[@title='All Saved Reports']/../..")
     tree.click_path("All Saved Reports")
     return VirtualIntelligence.SavedReportsSection(self.testsetup)
示例#3
0
 def reorder_elements(self, tab, box, *element_data):
     sel.force_navigate('service_dialog_edit', context={'dialog': self})
     if version.current_version() > "5.5":
         tree = accordion.tree("Dialog")
     else:
         tree = Tree("dialog_edit_treebox")
     tree.click_path(self.label, tab, box)
     list_ele = []
     for each_element in element_data:
         list_ele.append(each_element.get("ele_label"))
     ele_1 = self.element(list_ele[0])
     ele_2 = self.element(list_ele[1])
     sel.drag_and_drop(ele_1, ele_2)
     sel.click(form_buttons.save)
     flash.assert_no_errors()
示例#4
0
 def reorder_elements(self, tab, box, *element_data):
     sel.force_navigate('service_dialog_edit', context={'dialog': self})
     if version.current_version() > "5.5":
         tree = accordion.tree("Dialog")
     else:
         tree = Tree("dialog_edit_treebox")
     tree.click_path(self.label, tab, box)
     list_ele = []
     for each_element in element_data:
         list_ele.append(each_element.get("ele_label"))
     ele_1 = self.element(list_ele[0])
     ele_2 = self.element(list_ele[1])
     sel.drag_and_drop(ele_1, ele_2)
     sel.click(form_buttons.save)
     flash.assert_no_errors()
示例#5
0
def tree(name, *path):
    """Get underlying Tree() object. And eventually click path.

    If the accordion is not active, will be clicked.
    Attention! The object is 'live' so when it's obscured, it won't work!

    Usage:
        accordion.tree("Something").click_path("level 1", "level 2")
        accordion.tree("Something", "level 1", "level 2")  # is the same

    Args:
        *path: If specified, it will directly pass these parameters into click_path of Tree.
            Otherwise it returns the Tree object.
    """
    try:
        if not is_active(name):
            click(name)
    except AccordionItemNotFound:
        click(name)

    root_element = sel.element(locate(name))
    if sel.is_displayed(DYNATREE, root=root_element):
        # Dynatree detected
        tree = Tree(sel.element(DYNATREE, root=root_element))
    elif sel.is_displayed(TREEVIEW, root=root_element):
        # treeview detected
        el = sel.element(TREEVIEW, root=root_element)
        tree_id = sel.get_attribute(el, 'id')
        tree = BootstrapTreeview(tree_id)

    if path:
        return tree.click_path(*path)
    else:
        return tree
示例#6
0
def tree(name, *path):
    """Get underlying Tree() object. And eventually click path.

    If the accordion is not active, will be clicked.
    Attention! The object is 'live' so when it's obscured, it won't work!

    Usage:
        accordion.tree("Something").click_path("level 1", "level 2")
        accordion.tree("Something", "level 1", "level 2")  # is the same

    Args:
        *path: If specified, it will directly pass these parameters into click_path of Tree.
            Otherwise it returns the Tree object.
    """
    try:
        if not is_active(name):
            click(name)
    except AccordionItemNotFound:
        click(name)
    el = sel.element(
        # | for only single query
        "|".join([
            # Current tree for 5.4 (still with dhx)
            "../../div[contains(@class, 'dhxcont_global_content_area')]//"
            "ul[@class='dynatree-container']",
            # Newer accordion tree
            "../../..//div[@class='panel-body']//ul[@class='dynatree-container']"]),
        root=sel.element(locate(name)))
    tree = Tree(el)
    if path:
        return tree.click_path(*path)
    else:
        return tree
示例#7
0
def tree(name, *path):
    """Get underlying Tree() object. And eventually click path.

    If the accordion is not active, will be clicked.
    Attention! The object is 'live' so when it's obscured, it won't work!

    Usage:
        accordion.tree("Something").click_path("level 1", "level 2")
        accordion.tree("Something", "level 1", "level 2")  # is the same

    Args:
        *path: If specified, it will directly pass these parameters into click_path of Tree.
            Otherwise it returns the Tree object.
    """
    click(name)
    tree = Tree(
        sel.first_from(
            # Current tree
            "../../div[contains(@class, 'dhxcont_global_content_area')]//"
            "ul[@class='dynatree-container']",
            # Legacy tree
            "../../div[contains(@class, 'dhxcont_global_content_area')]//"
            "div[@class='containerTableStyle']//table[not(ancestor::tr[contains(@style,'none')])]",
            root=sel.element(locate(name))
        )
    )
    if path:
        return tree.click_path(*path)
    else:
        return tree
示例#8
0
 def update_element(self, second_element, element_data):
     sel.force_navigate('service_dialog_edit', context={'dialog': self})
     if version.current_version() > "5.5":
         tree = accordion.tree("Dialog")
     else:
         tree = Tree("dialog_edit_treebox")
     tree.click_path(self.label, self.tab_label, self.box_label)
     self.add_element(second_element)
     list_ele = []
     list_ele.append(element_data.get("ele_label"))
     list_ele.append(second_element.get("ele_label"))
     tree.click_path(self.label, self.tab_label, self.box_label)
     ele_1 = self.element(list_ele[0])
     ele_2 = self.element(list_ele[1])
     sel.drag_and_drop(ele_1, ele_2)
     sel.click(form_buttons.save)
     flash.assert_no_errors()
示例#9
0
 def update_element(self, second_element, element_data):
     navigate_to(self, 'Edit')
     if version.current_version() > "5.5":
         tree = accordion.tree("Dialog")
     else:
         tree = Tree("dialog_edit_treebox")
     tree.click_path(self.label, self.tab_label, self.box_label)
     self.add_element(second_element)
     list_ele = []
     list_ele.append(element_data.get("ele_label"))
     list_ele.append(second_element.get("ele_label"))
     tree.click_path(self.label, self.tab_label, self.box_label)
     ele_1 = self.element(list_ele[0])
     ele_2 = self.element(list_ele[1])
     sel.drag_and_drop(ele_1, ele_2)
     sel.click(form_buttons.save)
     flash.assert_no_errors()
 def update_element(self, second_element, element_data):
     navigate_to(self, 'Edit')
     if self.appliance.version > "5.5":
         tree = accordion.tree("Dialog")
     else:
         tree = Tree("dialog_edit_treebox")
     tree.click_path(self.label, self.tab_label, self.box_label)
     self.add_element(second_element)
     list_ele = []
     list_ele.append(element_data.get("ele_label"))
     list_ele.append(second_element.get("ele_label"))
     tree.click_path(self.label, self.tab_label, self.box_label)
     ele_1 = self.element(list_ele[0])
     ele_2 = self.element(list_ele[1])
     sel.drag_and_drop(ele_1, ele_2)
     sel.click(form_buttons.save)
     flash.assert_no_errors()
示例#11
0
def tree(name, *path):
    """Get underlying Tree() object. And eventually click path.

    If the accordion is not active, will be clicked.
    Attention! The object is 'live' so when it's obscured, it won't work!

    Usage:
        accordion.tree("Something").click_path("level 1", "level 2")
        accordion.tree("Something", "level 1", "level 2")  # is the same

    Args:
        *path: If specified, it will directly pass these parameters into click_path of Tree.
            Otherwise it returns the Tree object.
    """
    try:
        if not is_active(name):
            logger.debug(
                'Clicking accordion item %s because it is not active.', name)
            click(name)
    except AccordionItemNotFound:
        logger.debug(
            'Clicking accordion item %s because AccordionItemNotFound raised.',
            name)
        click(name)

    locator = locate(name)
    # Wait a bit for any of the trees to appear
    wait_for(lambda: sel.is_displayed(ANY_TREE, root=locator),
             quiet=True,
             silent_failure=True,
             delay=0.2,
             timeout=5)
    if sel.is_displayed(DYNATREE, root=locator):
        # Dynatree detected
        tree = Tree(sel.element(DYNATREE, root=locator))
    elif sel.is_displayed(TREEVIEW, root=locator):
        # treeview detected
        el = sel.element(TREEVIEW, root=locator)
        tree_id = sel.get_attribute(el, 'id')
        tree = BootstrapTreeview(tree_id)
    else:
        raise TypeError('None of the supported trees was detected.')

    if path:
        return tree.click_path(*path)
    else:
        return tree
示例#12
0
def tree(name, *path):
    """Get underlying Tree() object. And eventually click path.

    If the accordion is not active, will be clicked.
    Attention! The object is 'live' so when it's obscured, it won't work!

    Usage:
        accordion.tree("Something").click_path("level 1", "level 2")
        accordion.tree("Something", "level 1", "level 2")  # is the same

    Args:
        *path: If specified, it will directly pass these parameters into click_path of Tree.
            Otherwise it returns the Tree object.
    """
    try:
        if not is_active(name):
            logger.debug('Clicking accordion item %s because it is not active.', name)
            click(name)
    except AccordionItemNotFound:
        logger.debug('Clicking accordion item %s because AccordionItemNotFound raised.', name)
        click(name)

    locator = locate(name)
    # Wait a bit for any of the trees to appear
    wait_for(
        lambda: sel.is_displayed(ANY_TREE, root=locator),
        quiet=True, silent_failure=True, delay=0.2, timeout=5)
    if sel.is_displayed(DYNATREE, root=locator):
        # Dynatree detected
        tree = Tree(sel.element(DYNATREE, root=locator))
    elif sel.is_displayed(TREEVIEW, root=locator):
        # treeview detected
        el = sel.element(TREEVIEW, root=locator)
        tree_id = sel.get_attribute(el, 'id')
        tree = BootstrapTreeview(tree_id)
    else:
        raise TypeError('None of the supported trees was detected.')

    if path:
        return tree.click_path(*path)
    else:
        return tree
示例#13
0
    return get_server_name(get_ip_address())


def server_id():
    return get_server_id(get_ip_address())

nav.add_branch("configuration",
    {
        "configuration_settings":
        [
            lambda _: accordion.click("Settings"),
            {
                "cfg_settings_region":
                [
                    lambda _: settings_tree.click_path(
                        "Region: Region %d [%d]" % server_region_pair()
                    ),
                    {
                        "cfg_settings_region_details":
                        lambda _: tabs.select_tab("Details"),

                        "cfg_settings_region_cu_collection":
                        lambda _: tabs.select_tab("C & U Collection"),

                        "cfg_settings_region_my_company_categories":
                        lambda _: tabs.select_tab("My Company Categories"),

                        "cfg_settings_region_my_company_tags":
                        lambda _: tabs.select_tab("My Company Tags"),

                        "cfg_settings_region_import_tags":
示例#14
0
        ("add_button", (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Add']")),
        ("save_button", (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Save Changes']")),
        ("reset_button", (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Reset Changes']")),
        ("cancel_button", (By.CSS_SELECTOR, "div#buttons_off > ul#form_buttons > li > img[title='Cancel']")),
    ]
)


nav.add_branch(
    "chargeback",
    {
        "chargeback_rates": [
            nav.fn(partial(accordion.click, "Rates")),
            {
                "chargeback_rates_compute": [
                    lambda d: rate_tree.click_path("Rates", "Compute"),
                    {"chargeback_rates_compute_new": tb_select_new_chargeback},
                ],
                "chargeback_rates_compute_named": [
                    lambda d: rate_tree.click_path("Rates", "Compute", d["chargeback"].description),
                    {"chargeback_rates_compute_edit": tb_select_edit_chargeback},
                ],
                "chargeback_rates_storage": [
                    lambda d: rate_tree.click_path("Rates", "Storage"),
                    {"chargeback_rates_storage_new": tb_select_new_chargeback},
                ],
                "chargeback_rates_storage_named": [
                    lambda d: rate_tree.click_path("Rates", "Storage", d["chargeback"].description),
                    {"chargeback_rates_storage_edit": tb_select_edit_chargeback},
                ],
            },
示例#15
0

visible_tree = Tree("//div[@class='dhxcont_global_content_area']"
                    "[not(contains(@style, 'display: none'))]/div/div/div"
                    "/ul[@class='dynatree-container']")

menu.nav.add_branch(
    "services_workloads",
    {
        "service_vms_instances":
        [
            lambda _: accordion.tree("VMs & Instances", "All VMs & Instances"),
            {
                "service_vms_instances_filter_folder":
                [
                    lambda ctx: visible_tree.click_path(ctx["folder_name"]),
                    {
                        "service_vms_instances_filter":
                        lambda ctx: visible_tree.click_path(ctx["filter_name"])
                    }
                ]
            }
        ],

        "service_templates_images":
        [
            lambda _: (accordion.tree("Templates & Images", "All Templates & Images")),
            {
                "service_templates_images_filter_folder":
                [
                    lambda ctx: visible_tree.click_path(ctx["folder_name"]),
示例#16
0
    ('retirement_date_text', Calendar("miq_date_1")),
    ('retirement_warning_select', Select("//select[@id='retirement_warn']"))
])

retire_remove_button = "//span[@id='remove_button']/a/img"

nav.add_branch(
    'infrastructure_virtual_machines',
    {
        "infra_vm_and_templates":
        [
            lambda _: accordion.tree("VMs & Templates", "All VMs & Templates"),
            {
                "vm_templates_provider_branch":
                [
                    lambda ctx: visible_tree.click_path(ctx["provider_name"]),
                    {
                        "datacenter_branch":
                        [
                            lambda ctx: visible_tree.click_path(ctx["datacenter_name"]),
                            {
                                "infra_vm_obj": lambda ctx: visible_tree.click_path(ctx["vm_name"]),
                            }
                        ],
                    }
                ],

                "vm_templates_archived_branch":
                [
                    lambda ctx: visible_tree.click_path("<Archived>"),
                    {
示例#17
0
        ('storage_fixed_1', _mkitem(0)),
        ('storage_fixed_2', _mkitem(1)),
        ('storage_alloc', _mkitem(2)),
        ('storage_used', _mkitem(3)),
        ('add_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Add']")),
        ('save_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Save Changes']")),
        ('reset_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Reset Changes']")),
        ('cancel_button', (By.CSS_SELECTOR,
                           "div#buttons_off > ul#form_buttons > li > img[title='Cancel']"))])


nav.add_branch('chargeback',
               {'chargeback_rates':
                [nav.fn(partial(accordion.click, "Rates")),
                 {'chargeback_rates_compute':
                  [lambda d: rate_tree.click_path('Rates', 'Compute'),
                   {'chargeback_rates_compute_new': tb_select_new_chargeback}],
                  'chargeback_rates_compute_named':
                  [lambda d: rate_tree.click_path('Rates', 'Compute', d['chargeback'].description),
                   {'chargeback_rates_compute_edit': tb_select_edit_chargeback}],
                  'chargeback_rates_storage':
                  [lambda d: rate_tree.click_path('Rates', 'Storage'),
                   {'chargeback_rates_storage_new': tb_select_new_chargeback}],
                  'chargeback_rates_storage_named':
                  [lambda d: rate_tree.click_path('Rates', 'Storage', d['chargeback'].description),
                   {'chargeback_rates_storage_edit': tb_select_edit_chargeback}]}],
                'chargeback_assignments': nav.fn(partial(accordion.click, "Assignments"))})


HOURLY = 'hourly'
DAILY = 'daily'
示例#18
0
        ('add_btn', "//img[@alt='Move selected VMs to left']"),
        ('remove_btn', "//img[@alt='Move selected VMs to right']"),
        ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
    ])


nav.add_branch(
    "clouds_instances",
    {
        "clouds_instances_by_provider":
        [
            lambda _: accordion.tree("Instances by Provider", "Instances by Provider"),
            {
                "clouds_instances_provider_branch":
                [
                    lambda ctx: visible_tree.click_path(ctx["provider_name"]),
                    {
                        "availability_zone_branch":
                        [
                            lambda ctx: visible_tree.click_path(ctx["availability_zone"]),
                            {
                                "clouds_instance_obj":
                                lambda ctx: visible_tree.click_path(ctx["instance_name"])
                            }
                        ]
                    }
                ],

                "clouds_instances_archived_branch":
                [
                    lambda ctx: visible_tree.click_path('<Archived>'),
示例#19
0
        'cancel_button': make_button("Cancel"),
        'add_button': make_button("Add"),
    },
    identifying_loc="//div[@id='buttons_on']/ul[@id='form_buttons']",
)

records_table = Table("//div[@id='records_div']/table[@class='style3']")

nav.add_branch("configuration",
    {
        "configuration_settings":
        [
            lambda _: accordion.click("Settings"),
            {
                "cfg_settings_region":
                lambda _: settings_tree.click_path("Region: Region"),

                "cfg_settings_defaultzone":
                lambda _: settings_tree.click_path("Region: Region", "Zones", "Default Zone"),

                "cfg_settings_schedules":
                [
                    lambda _: settings_tree.click_path("Region: Region", "Schedules"),
                    {
                        "cfg_settings_schedule":
                        [
                            lambda ctx: records_table.click_cell("name", ctx["schedule_name"]),
                            {
                                "cfg_settings_schedule_edit":
                                lambda _: tb.select("Configuration", "Edit this Schedule")
                            }

def accordion_fn(acc, tree):
    def f(_):
        accordion.click(acc)
        visible_tree.click_path(tree)

    return f


nav.add_branch(
    'infrastructure_virtual_machines', {
        "infra_vm_and_templates": [
            accordion_fn("VMs & Templates", "All VMs & Templates"), {
                "vm_templates_provider_branch": [
                    lambda ctx: visible_tree.click_path(ctx["provider_name"]),
                    {
                        "datacenter_branch": [
                            lambda ctx: visible_tree.click_path(ctx[
                                "datacenter_name"]), {
                                    "infra_vm_obj":
                                    lambda ctx: visible_tree.click_path(ctx[
                                        "vm_name"]),
                                }
                        ],
                    }
                ],
                "vm_templates_archived_branch": [
                    lambda ctx: visible_tree.click_path('Archived'), {
                        "infra_archive_obj":
                        lambda ctx: visible_tree.click_path(ctx["archive_name"]
示例#21
0
       the item in the path that was missing was the last item."""
    data = e.args[0]  # the data mapping
    return isinstance(e, exceptions.CandidateNotFound) and data['index'] == len(data['path']) - 1


def open_order_dialog_func(_):
    datastore_tree()
    cfg_btn("Edit Priority Order of Domains")

nav.add_branch(
    'automate_explorer',
    {
        'automate_explorer_tree_path':
        [lambda context:
            context.tree_item.navigate_tree() if context.tree_item is not None
            else tree.click_path('Datastore'),
         {
             'automate_explorer_table_select':
             [lambda ctx: table_select(ctx['table_item'].name_in_table),
              {
                  'automate_explorer_edit':
                  lambda context: context.tree_item.nav_edit(),
                  'automate_explorer_delete':
                  lambda _: cfg_btn('Remove selected Items', invokes_alert=True)}],

             'automate_explorer_namespace_new': lambda _: cfg_btn('Add a New Namespace'),
             'automate_explorer_domain_new': lambda _: cfg_btn('Add a New Domain'),
             'automate_explorer_class_new': lambda _: cfg_btn('Add a New Class'),
             "automate_explorer_domain_edit": lambda _: cfg_btn("Edit this Domain"),
             'automate_explorer_method_edit': lambda _: cfg_btn('Edit this Method'),
             'automate_explorer_instance_edit': lambda _: cfg_btn('Edit this Instance'),
示例#22
0
def table_select(name):
    cb = datastore_checkbox(name)
    wait_for(sel.is_displayed, [cb], num_sec=5, delay=0.2)
    sel.check(datastore_checkbox(name))


def open_order_dialog_func(_):
    datastore_tree()
    cfg_btn("Edit Priority Order of Domains")


nav.add_branch(
    'automate_explorer', {
        'automate_explorer_tree_path': [
            lambda context: context.tree_item.navigate_tree()
            if context.tree_item is not None else tree.click_path('Datastore'),
            {
                'automate_explorer_table_select': [
                    lambda ctx: table_select(ctx['table_item'].name_in_table),
                    {
                        'automate_explorer_edit':
                        lambda context: context.tree_item.nav_edit(),
                        'automate_explorer_delete':
                        lambda _: cfg_btn('Remove selected Items',
                                          invokes_alert=True)
                    }
                ],
                'automate_explorer_namespace_new':
                lambda _: cfg_btn('Add a New Namespace'),
                'automate_explorer_domain_new':
                lambda _: cfg_btn('Add a New Domain'),
示例#23
0
    ('description_tarea', "//textarea[@id='description']"),
    ('parent_sel', Select("//select[@name='chosen_parent']")),
    ('child_sel', Select("//select[@id='kids_chosen']", multi=True)),
    ('vm_sel', Select("//select[@id='choices_chosen']", multi=True)),
    ('add_btn', "//img[@alt='Move selected VMs to left']"),
    ('remove_btn', "//img[@alt='Move selected VMs to right']"),
    ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
])

nav.add_branch(
    "clouds_instances", {
        "clouds_instances_by_provider": [
            lambda _: accordion.
            tree("Instances by Provider", "Instances by Provider"), {
                "clouds_instances_provider_branch": [
                    lambda ctx: visible_tree.click_path(ctx["provider_name"]),
                    {
                        "availability_zone_branch": [
                            lambda ctx: visible_tree.click_path(ctx[
                                "availability_zone"]), {
                                    "clouds_instance_obj":
                                    lambda ctx: visible_tree.click_path(ctx[
                                        "instance_name"])
                                }
                        ]
                    }
                ],
                "clouds_instances_archived_branch": [
                    lambda ctx: visible_tree.click_path('<Archived>'), {
                        "clouds_instance_archive_obj":
                        lambda ctx: visible_tree.click_path(ctx["archive_name"]
示例#24
0
        ("tag_category", Select("select#cbtag_cat")),
        # Common - selection table
        ("selections", AssignFormTable({
            LOWEST: (
                "//div[@id='cb_assignment_div']/fieldset/table[contains(@class, 'style1')]"
                "/tbody/tr/td/table"),
            "5.4": "//div[@id='cb_assignment_div']/table[contains(@class, 'table')]",
        })),
        ('save_button', form_buttons.save)])


nav.add_branch('chargeback',
               {'chargeback_rates':
                [nav.fn(partial(accordion.click, "Rates")),
                 {'chargeback_rates_compute':
                  [lambda d: rate_tree.click_path('Rates', 'Compute'),
                   {'chargeback_rates_compute_new': tb_select_new_chargeback}],
                  'chargeback_rates_compute_named':
                  [lambda d: rate_tree.click_path('Rates', 'Compute', d['chargeback'].description),
                   {'chargeback_rates_compute_edit': tb_select_edit_chargeback}],
                  'chargeback_rates_storage':
                  [lambda d: rate_tree.click_path('Rates', 'Storage'),
                   {'chargeback_rates_storage_new': tb_select_new_chargeback}],
                  'chargeback_rates_storage_named':
                  [lambda d: rate_tree.click_path('Rates', 'Storage', d['chargeback'].description),
                   {'chargeback_rates_storage_edit': tb_select_edit_chargeback}]}],
                'chargeback_assignments':
                [nav.fn(partial(accordion.click, "Assignments")),
                 {'chargeback_assignments_compute':
                  lambda d: assignment_tree.click_path('Assignments', 'Compute'),
                 'chargeback_assignments_storage':
示例#25
0
        ('storage_fixed_1', _mkitem(0)),
        ('storage_fixed_2', _mkitem(1)),
        ('storage_alloc', _mkitem(2)),
        ('storage_used', _mkitem(3)),
        ('add_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Add']")),
        ('save_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Save Changes']")),
        ('reset_button', (By.CSS_SELECTOR, "ul#form_buttons > li > img[title='Reset Changes']")),
        ('cancel_button', (By.CSS_SELECTOR,
                           "div#buttons_off > ul#form_buttons > li > img[title='Cancel']"))])


nav.add_branch('chargeback',
               {'chargeback_rates':
                [nav.fn(partial(accordion.click, "Rates")),
                 {'chargeback_rates_compute':
                  [lambda d: rate_tree.click_path('Rates', 'Compute'),
                   {'chargeback_rates_compute_new': tb_select_new_chargeback}],
                  'chargeback_rates_compute_named':
                  [lambda d: rate_tree.click_path('Rates', 'Compute', d['chargeback'].description),
                   {'chargeback_rates_compute_edit': tb_select_edit_chargeback}],
                  'chargeback_rates_storage':
                  [lambda d: rate_tree.click_path('Rates', 'Storage'),
                   {'chargeback_rates_storage_new': tb_select_new_chargeback}],
                  'chargeback_rates_storage_named':
                  [lambda d: rate_tree.click_path('Rates', 'Storage', d['chargeback'].description),
                   {'chargeback_rates_storage_edit': tb_select_edit_chargeback}]}],
                'chargeback_assignments': nav.fn(partial(accordion.click, "Assignments"))})


HOURLY = 'hourly'
DAILY = 'daily'