behave_odoo

behave_odoo is a Python package that provides a collection of helper functions designed to simplify the process of writing behave tests for Odoo 14.

The package includes functions for navigating the Odoo interface, interacting with form fields, and performing common actions within the Odoo environment.

import behave_odoo as bodoo

@given('the user log in on the Odoo Instance')
def step_impl(context):
    bodoo.login(context)
 1"""
 2`behave_odoo` is a Python package that provides a collection of helper functions designed to simplify the process of writing behave tests for Odoo 14. 
 3
 4The package includes functions for navigating the Odoo interface, interacting with form fields, and performing common actions within the Odoo environment.
 5
 6
 7```python
 8import behave_odoo as bodoo
 9
10@given('the user log in on the Odoo Instance')
11def step_impl(context):
12    bodoo.login(context)
13```
14
15"""
16from .behave_odoo import (
17    login,
18    click_menu_item,
19    navigate_menu,
20    set_text_field,
21    set_select_field,
22    set_autocomplete_field,
23    select_dropdown_item,
24    click_button,
25    switch_form_tab,
26    ensure_readonly_mode,
27    get_first_fields_from_tree_view,
28    is_tree_view_by_column_name,
29    switch_module,
30    click_smart_button,
31)
32
33__all__ = [
34    "login",
35    "click_menu_item",
36    "navigate_menu",
37    "set_text_field",
38    "set_select_field",
39    "set_autocomplete_field",
40    "select_dropdown_item",
41    "click_button",
42    "switch_form_tab",
43    "ensure_readonly_mode",
44    "get_first_fields_from_tree_view",
45    "is_tree_view_by_column_name",
46    "switch_module",
47    "click_smart_button",
48]
def login(context, **kwargs):
28def login(context, **kwargs):
29    """
30    Login to Odoo.
31
32    ```python
33    bodoo.login(context)
34    ```
35
36    By default, it uses the following context variables from behave.ini:
37    - odoo_url
38    - odoo_username
39    - odoo_password
40    :param context: behave context
41    """
42    odoo_url = kwargs.get("odoo_url", context.odoo_url)
43    odoo_username = kwargs.get("odoo_username", context.odoo_username)
44    odoo_password = kwargs.get("odoo_password", context.odoo_password)
45
46    context.browser.get(odoo_url + "/web")
47    username_input = context.browser.find_element(By.NAME, "login")
48    username_input.send_keys(odoo_username)
49    password_input = context.browser.find_element(By.NAME, "password")
50    password_input.send_keys(odoo_password)
51    password_input.submit()

Login to Odoo.

bodoo.login(context)

By default, it uses the following context variables from behave.ini:

  • odoo_url
  • odoo_username
  • odoo_password
Parameters
  • context: behave context
def click_menu_item(context, menu_text):
56def click_menu_item(context, menu_text):
57    """
58    Clicks on the main menu item that contains the given text
59
60    ```python
61    bodoo.click_menu_item(context, "Sales")
62    ```
63
64    :param context: behave context
65    :param menu_text: text to search for in the menu item
66    """
67    menu_item_xpath = \
68        f"//a[contains(@class, 'dropdown-toggle') and contains(normalize-space(), '{menu_text}')]"
69
70    menu_item = WebDriverWait(context.browser, 3).until(
71        EC.element_to_be_clickable((By.XPATH, menu_item_xpath)))
72    menu_item.click()

Clicks on the main menu item that contains the given text

bodoo.click_menu_item(context, "Sales")
Parameters
  • context: behave context
  • menu_text: text to search for in the menu item
def set_text_field(context, field_name, value):
106def set_text_field(context, field_name, value):
107    """
108    Sets the value of the text field with the given name
109    
110    ```python
111    bodoo.set_text_field(context, "name", "John Doe")
112    ```       
113
114    :param context: behave
115    :param field_name: label of the text field
116    :param value: value to set
117    """
118    element = WebDriverWait(context.browser, 5).until(
119        EC.presence_of_element_located(
120            (By.XPATH, f"//input[contains(@name,'{field_name}')]"))
121    )
122
123    element.send_keys(value)

Sets the value of the text field with the given name

bodoo.set_text_field(context, "name", "John Doe")
Parameters
  • context: behave
  • field_name: label of the text field
  • value: value to set
def set_select_field(context, select_item, option):
126def set_select_field(context, select_item, option):
127    """
128    Set an option in a select field with the given name
129    
130    ```python
131    bodoo.set_select_field(context, "country_id", "United States")
132    ```       
133        
134    :param context: behave
135    :param select_item: name of the select field
136    :param option: (visible) value to set
137    """
138    select_element = WebDriverWait(context.browser, 5).until(
139        EC.presence_of_element_located(
140            (By.XPATH, f"//select[contains(@name, '{select_item}')]"))
141    )
142    select = Select(select_element)
143    select.select_by_visible_text(option)

Set an option in a select field with the given name

bodoo.set_select_field(context, "country_id", "United States")
Parameters
  • context: behave
  • select_item: name of the select field
  • option: (visible) value to set
def set_autocomplete_field(context, field_name, chars):
146def set_autocomplete_field(context, field_name, chars):
147    """
148    Set an autocomplete (one2many, many2one, many2many) field.
149
150    Introduce the characters and press tab to select the first highlighted option.
151    
152    ```python
153    bodoo.set_autocomplete_field(context, "partner_id", "John Do")
154    ```       
155        
156    :param context: behave
157    :param field_name: name of the select field
158    :param chars: string to enter prior to tab
159    """
160
161    autocomplete_input = WebDriverWait(context.browser, 5).until(
162        EC.element_to_be_clickable(
163            (By.XPATH, f"//div[@name='{field_name}']//input[contains(@class, 'o_input')]"))
164    )
165    autocomplete_input.click()
166    autocomplete_input.send_keys(chars)
167    autocomplete_input.send_keys(Keys.TAB)

Set an autocomplete (one2many, many2one, many2many) field.

Introduce the characters and press tab to select the first highlighted option.

bodoo.set_autocomplete_field(context, "partner_id", "John Do")
Parameters
  • context: behave
  • field_name: name of the select field
  • chars: string to enter prior to tab
def select_dropdown_item(context, option_text):
170def select_dropdown_item(context, option_text):
171    """
172    Selects the dropdown item with the given text
173    
174    ```python
175    bodoo.select_dropdown_item(context, "Delete")
176    ```       
177        
178    :param context: behave context
179    :param option_text: text of the dropdown item
180    """
181    option_element = WebDriverWait(context.browser, 5).until(
182        EC.presence_of_element_located(
183            (By.XPATH, f"//ul[@class='o_dropdown_menu dropdown-menu show']//a[contains(text(), '{option_text}')]"))
184    )
185    option_element.click()

Selects the dropdown item with the given text

bodoo.select_dropdown_item(context, "Delete")
Parameters
  • context: behave context
  • option_text: text of the dropdown item
def click_button(context, button_text):
188def click_button(context, button_text):
189    """
190    Clicks on the button with the given text
191
192    
193    ```python
194    bodoo.click_button(context, "Create")
195    ```       
196    
197    :param context: behave context
198    :param button_text: text of the button
199    """
200    # Buscar el elemento del botón por su texto
201    button_element = WebDriverWait(context.browser, 5).until(
202        EC.presence_of_element_located(
203            (By.XPATH,
204             f"//button[contains(text(), '{button_text}')] | //button//span[contains(text(), '{button_text}')]"))
205
206    )
207
208    # Hacer clic en el botón
209    button_element.click()

Clicks on the button with the given text

bodoo.click_button(context, "Create")
Parameters
  • context: behave context
  • button_text: text of the button
def switch_form_tab(context, tab_name):
213def switch_form_tab(context, tab_name):
214    """
215    Switches to an Odoo tab in form view
216    ```python
217        bodoo.switch_form_tab(context, "Sales")
218    ```    
219    :param context: behave context
220    :param tab_name: name of the tab to switch to
221    """
222    tab_xpath = f"//a[contains(normalize-space(), '{tab_name}') and @data-toggle='tab' and @role='tab']"
223    WebDriverWait(context.browser, 5).until(
224        EC.visibility_of_element_located((By.XPATH, tab_xpath))
225    ).click()

Switches to an Odoo tab in form view

    bodoo.switch_form_tab(context, "Sales")
Parameters
  • context: behave context
  • tab_name: name of the tab to switch to
def ensure_readonly_mode(context):
228def ensure_readonly_mode(context):
229    """
230    Ensure that the current view is in readonly mode
231
232    ```python
233    bodoo.ensure_readonly_mode(context)
234    ```    
235    :param context: behave context
236    """
237    WebDriverWait(context.browser, 1).until(
238        EC.presence_of_element_located(
239            (By.XPATH, "//button[contains(@class, 'o_form_button_edit')]"))
240    )
241    WebDriverWait(context.browser, 1).until(
242        EC.visibility_of_element_located(
243            (By.XPATH, "//div[contains(@class, 'o_form_readonly')]"))
244    )

Ensure that the current view is in readonly mode

bodoo.ensure_readonly_mode(context)
Parameters
  • context: behave context
def get_first_fields_from_tree_view(context):
249def get_first_fields_from_tree_view(context):
250    """
251    Returns the second td content (the first is the checkbox) of each row in the tree view
252
253    ```python
254    bodoo.get_first_fields_from_tree_view(context)
255    ```    
256    :param context: behave context
257    :return: list of strings
258    """
259    elements = context.browser.find_elements(By.XPATH,
260                                             "//div[contains(@class, 'o_list_view')]//table[contains(@class, 'o_list_table')]/tbody[contains(@class, 'ui-sortable')]/tr/td[2]")
261    return [x.text for x in elements]

Returns the second td content (the first is the checkbox) of each row in the tree view

bodoo.get_first_fields_from_tree_view(context)
Parameters
  • context: behave context
Returns

list of strings

def is_tree_view_by_column_name(context, column_name):
264def is_tree_view_by_column_name(context, column_name):
265    """
266    Checks if the current view is a tree view and the second column has a given name.
267
268    (The first column is the checkbox)
269
270    ```python
271    bodoo.is_tree_view_by_column_name(context, "Name")
272    ```    
273    :param context: behave context
274    :param column_name: The name to check for in the second column
275    :return: True if the conditions are met, False otherwise
276    """
277    try:
278        WebDriverWait(context.browser, 10).until(
279            EC.presence_of_element_located(
280                (By.XPATH, f"//th[2][contains(text(), '{column_name}')]"))
281        )
282        return True
283    except NoSuchElementException:
284        return False

Checks if the current view is a tree view and the second column has a given name.

(The first column is the checkbox)

bodoo.is_tree_view_by_column_name(context, "Name")
Parameters
  • context: behave context
  • column_name: The name to check for in the second column
Returns

True if the conditions are met, False otherwise

def switch_module(context, module_name):
289def switch_module(context, module_name):
290    """
291    Switches to the given Odoo module (snake_case)
292
293    ```python
294    bodoo.switch_module(context, "sale_management")
295    ```
296    
297    :param context: behave context
298    :param module_name: name of the module
299    """
300    app_icon_found = _find_and_click_app_icon(context, module_name)
301
302    if not app_icon_found:
303        _open_drawer_if_exists(context)
304        app_icon_found = _find_and_click_app_icon(context, module_name)
305        if not app_icon_found:
306            _find_and_click_module_in_dropdown(context, module_name)

Switches to the given Odoo module (snake_case)

bodoo.switch_module(context, "sale_management")
Parameters
  • context: behave context
  • module_name: name of the module
def click_smart_button(context, button_css_selector):
358def click_smart_button(context, button_css_selector):
359    """
360    Clicks on the smart button with the given css selector
361    :param context: behave context
362    :param button_css_selector: css selector of the smart button
363    (ALPHA: Untested)
364    """
365    button = WebDriverWait(context.browser, 5).until(
366        EC.element_to_be_clickable((By.CSS_SELECTOR, button_css_selector)))
367    button.click()

Clicks on the smart button with the given css selector

Parameters
  • context: behave context
  • button_css_selector: css selector of the smart button (ALPHA: Untested)