Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configDB - QA #24

Open
nebeskimehanicar opened this issue Jan 23, 2025 · 4 comments
Open

configDB - QA #24

nebeskimehanicar opened this issue Jan 23, 2025 · 4 comments

Comments

@nebeskimehanicar
Copy link

I would like to summarize what additional things I found so far in the API system:

GENERIC MODES

The API does not CREATE Generic Modes, and no ID is returned when listing them.

In order to CREATE them you need to use web interface and retrieve their IDs manually.

The API also doesn't support UPDATE, so you need to update them via the web interface as well.

In order to CREATE and UPDATE Generic Modes automatically, I created WEB functions that are doing that using selenium web-driver.

LIST, RETRIEVE, and DESTROY operations work as expected through the API.

However, I also added WEB function for listing GM with their IDs since they are not returned in the table by default.

GENERIC MODE GROUPS

Exactly the same issues as explained above for the GM.

I would add also one addition thing regarding GMG and their creation.
Creating a NEW GMG fails if the INSTRUMENT_TYPE has already been used for the creation of another generic mode group.
This means I can only create a new generic mode group using a "new" or "unused" instrument type.
This was tested also manually trough configDB.

Attached is a screenshot capturing the bug.

Image

MODE TYPES

There is no API function for Mode Types (http://127.0.0.1:7000/admin/hardware/modetype) and I think it would be nice to have this, since for everything else API exists.

Python code

I am sharing my python code including all API and WEB functions that I created and tested locally, and are working well with confingDB on my computer. Maybe someone will find it useful :)

P.S. When I have time to write and test WEB functions for Mode Types I will attached them as well.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Jan 2025

@author: nikola knezevic AOB
"""

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import json


def list_components(BASE_URL, COMPONENT, filters=None):
    """
    Retrieve and list all components with optional filters.

    Args:
        BASE_URL: Base URL of your ConfigDB.
        COMPONENT: Possible ConfigDB component.
        filters (dict, optional): Optional query parameters for filtering.

    Returns:
        list: List of components or error message.
    """
    endpoint = f'{BASE_URL}/{COMPONENT}/'
    all_components = []
    while endpoint:
        response = requests.get(endpoint, params=filters)
        print(f"Status Code --> [{response.status_code} : {response.reason}]")
        if response.status_code == 200:
            json_response = response.json()
            all_components.extend(json_response['results'])
            endpoint = json_response.get('next')
    print(f"Total {COMPONENT} retrieved: {len(all_components)}")
    return all_components


def get_OE_id(BASE_URL, USERNAME, PASSWORD, oe):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/opticalelement/")
        # Locate the rows in the table body
        rows = driver.find_elements(By.CSS_SELECTOR, "table#result_list tbody tr")       
        # Initialize a list to store extracted data
        data = []
        # Loop through each row and extract required information
        for row in rows:
            name = row.find_element(By.CSS_SELECTOR, "th.field-name a").text
            value = row.find_element(By.CSS_SELECTOR, "td.action-checkbox input").get_attribute("value")
            code = row.find_element(By.CSS_SELECTOR, "td.field-code").text
            data.append({"name": name, "code": code, "id": value})
        oe_id = next((item['id'] for item in data if item['name'] == oe['name'] and item['code'] == oe['code']), None)
        driver.quit()
        return int(oe_id)
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return None


def list_OE_ids(BASE_URL, USERNAME, PASSWORD):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/opticalelement/")
        print("Accessed optical element form.")
        # Locate the rows in the table body
        rows = driver.find_elements(By.CSS_SELECTOR, "table#result_list tbody tr")
        # Initialize a list to store extracted data
        data = []   
        # Loop through each row and extract required information
        for row in rows:
            name = row.find_element(By.CSS_SELECTOR, "th.field-name a").text
            value = row.find_element(By.CSS_SELECTOR, "td.action-checkbox input").get_attribute("value")
            code = row.find_element(By.CSS_SELECTOR, "td.field-code").text
            data.append({"name": name, "code": code, "id": value})     
        # Print the extracted data
        print ('Optical elements and their IDs:')
        for entry in data:
            print(entry)
        driver.quit()
        return data
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return data


def list_GM_ids(BASE_URL, USERNAME, PASSWORD):   
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Go to Generic Modes page
        driver.get(f"{BASE_URL}/admin/hardware/genericmode/")
        # Locate the rows in the table body
        rows = driver.find_elements(By.XPATH, "//table[@id='result_list']/tbody/tr")       
        # Initialize a list to store extracted data
        data = []     
        # Loop through each row and extract required information
        for row in rows:
            # Extract the name (from the <a> tag inside <th class="field-name">)
            name_element = row.find_element(By.XPATH, ".//th[@class='field-name']/a")
            name = name_element.text          
            # Extract the ID (from the <input> tag inside <td class="action-checkbox">)
            id_element = row.find_element(By.XPATH, ".//td[@class='action-checkbox']/input")
            value = id_element.get_attribute("value")            
            # Extract the code (from the <td class="field-code">)
            code_element = row.find_element(By.XPATH, ".//td[@class='field-code']")
            code = code_element.text        
            # Append the extracted data to the list
            data.append({"name": name, "code": code, "id": value})       
        # Print the extracted data
        print("Generic Mode elements and their IDs:")
        for entry in data:
            print(entry)
        driver.quit()
        return data
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return data


def list_GMG_ids(BASE_URL, USERNAME, PASSWORD):   
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Go to Generic Modes page
        driver.get(f"{BASE_URL}/admin/hardware/genericmodegroup/")
        # Locate the rows in the table body
        rows = driver.find_elements(By.XPATH, "//table[@id='result_list']/tbody/tr")  
        # Initialize a list to store extracted data
        data = [] 
        # Loop through each row and extract required information
        for row in rows:
            # Extract the instrument type (from the <a> tag inside <th class="field-instrument_type nowrap">)
            instrument_type_element = row.find_element(By.XPATH, ".//th[@class='field-instrument_type nowrap']/a")
            instrument_type = instrument_type_element.text        
            # Extract the type (from the <td class="field-type nowrap">)
            type_element = row.find_element(By.XPATH, ".//td[@class='field-type nowrap']")
            mode_type = type_element.text              
            # Extract the default value (from the <td class="field-default nowrap">)
            default_element = row.find_element(By.XPATH, ".//td[@class='field-default nowrap']")
            default = default_element.text              
            # Extract the generic mode group (from the <td class="field-__str__">)
            generic_mode_group_element = row.find_element(By.XPATH, ".//td[@class='field-__str__']")
            generic_mode_group = generic_mode_group_element.text          
            # Extract the ID (from the <input> tag inside <td class="action-checkbox">)
            id_element = row.find_element(By.XPATH, ".//td[@class='action-checkbox']/input")
            value = id_element.get_attribute("value")
               
            # Append the extracted data to the list
            data.append({
                         "instrument_type": instrument_type,
                         "type": mode_type,
                         "default": default,
                         "generic_mode_group": generic_mode_group,
                         "id": value
                       })
        # Print the extracted data
        print("Generic Mode Groups and their IDs:")
        for entry in data:
            print(entry)           
        driver.quit()
        return data
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return data


def create_component(BASE_URL, COMPONENT, AUTHORIZATION_TOKEN, component_new):
    """
    Create a new component with the provided data.

    Args:
        BASE_URL: Base URL of your ConfigDB.
        COMPONENT: Possible ConfigDB component.
        AUTHORIZATION_TOKEN: Authorization token (super-user or local configDB token).
        component_new (dict): The JSON payload containing the new component data.

    Returns:
        dict: Newly created component details or error message.
    """
    endpoint = f'{BASE_URL}/{COMPONENT}/'
    headers = {"Authorization": f"Token {AUTHORIZATION_TOKEN}"}
    response = requests.post(endpoint, data=component_new, headers=headers)
    print(f"Status Code --> [{response.status_code} : {response.reason}]")
    if response.status_code == 201:
        json_response = response.json()
        if COMPONENT == 'opticalelements':
            oe = {'name': component_new['name'], 'code': component_new['code']}
            oe_id = get_OE_id(oe)
            print (f"New {COMPONENT[:-1]} with 'id = {oe_id}' was successfully created.")
        else:
            print (f"New {COMPONENT[:-1]} with 'id = {json_response['id']}' was successfully created.")
        return json_response
    else:
        print (f"Failed to create new {COMPONENT[:-1]}.")
        return {}


def login_and_create_OEG(BASE_URL, USERNAME, PASSWORD, oeg_new):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/opticalelementgroup/add/")
        print("Accessed optical element group form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        name_field = driver.find_element(By.NAME, 'name')
        name_field.send_keys(oeg_new['name'])
        #------------------------------------------------------------------------------------------------------------------------
        type_field = driver.find_element(By.NAME, 'type')
        type_field.send_keys(oeg_new['type'])
        #------------------------------------------------------------------------------------------------------------------------
        # Select multiple options
        optical_elements_field = driver.find_element(By.ID, 'id_optical_elements')
        my_list_of_optical_elements = [e['name'] for e in oeg_new['optical_elements']]
        for option in optical_elements_field.find_elements(By.TAG_NAME, 'option'):
            if option.text in my_list_of_optical_elements:
                option.click()
        #------------------------------------------------------------------------------------------------------------------------
        all_optical_elements_options = [option.text for option in optical_elements_field.find_elements(By.TAG_NAME, 'option')]
        non_existing_elements = []
        for my_option in my_list_of_optical_elements:
            if my_option not in all_optical_elements_options:
                print ("Unable to add optical element with the name '" + my_option + "' because it doesn't exist in the configDB.")
                non_existing_elements.append(my_option)
        #------------------------------------------------------------------------------------------------------------------------
        if non_existing_elements == my_list_of_optical_elements:
            print ('No optical elements to add to the optical element group. Optical element group will not be created.')
            driver.quit()
            return None
        #------------------------------------------------------------------------------------------------------------------------
        overhead_field = driver.find_element(By.NAME, 'element_change_overhead')
        # Clear the field first
        overhead_field.clear()
        # Send the value
        overhead_field.send_keys(oeg_new['element_change_overhead'])
        #------------------------------------------------------------------------------------------------------------------------
        if 'default' in list(oeg_new.keys()):
            default_elements_field = driver.find_element(By.ID, 'id_default')                     
            my_default_element = oeg_new['default']['name']
            my_list_of_optical_elements_new = [e for e in my_list_of_optical_elements if e not in non_existing_elements]
            if my_default_element in my_list_of_optical_elements_new:              
                for option in default_elements_field.find_elements(By.TAG_NAME, 'option'):
                    if option.text == my_default_element:
                        option.click()
                        break        
            else:               
                print ("Unable to set default element with the name '" + my_default_element + "' because it doesn't "\
                       "exist among the added optical elements ['" + "', '".join(my_list_of_optical_elements_new) + "'] for this group.")
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the group was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Optical element group added successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        # Go to Optical Element Groups page and return ID of the newly created group
        driver.get(f"{BASE_URL}/admin/hardware/opticalelementgroup/")
        # Initialize lists to store the IDs
        ids = []
        # Find all rows in the table body
        rows = driver.find_elements(By.XPATH, "//table[@id='result_list']/tbody/tr")
        # Loop through each row and extract ID
        for row in rows:         
            # Extract the ID (from the <a> tag inside <th class="field-id">)
            id_element = row.find_element(By.XPATH, ".//th[@class='field-id']/a")
            ids.append(int(id_element.text))
        # Get group ID
        sorted_ids = sorted(ids)
        new_group_id = sorted_ids[-1]
        print (f"New opticalelementgroup with 'id = {new_group_id}' was successfully created.")
        driver.quit()
        return new_group_id
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return None


def login_and_create_GM(BASE_URL, USERNAME, PASSWORD, new_gm):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/genericmode/add/")
        print("Accessed generic mode form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        name_field = driver.find_element(By.ID, 'id_name')
        name_field.send_keys(new_gm['name'])
        #------------------------------------------------------------------------------------------------------------------------
        code_field = driver.find_element(By.ID, 'id_code')
        code_field.send_keys(new_gm['code'])
        #------------------------------------------------------------------------------------------------------------------------
        overhead_field = driver.find_element(By.ID, 'id_overhead')
        # Clear the field first
        overhead_field.clear()
        # Send the value
        overhead_field.send_keys(new_gm['overhead'])
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the checkbox element
        checkbox = driver.find_element(By.ID, 'id_schedulable')
        # Check if the checkbox is already in the desired state
        checkbox_state = new_gm['schedulable']
        if checkbox_state != checkbox.is_selected():
            checkbox.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the validation schema element
        validation_schema = driver.find_element(By.ID, "id_validation_schema")
        # Convert the dictionary to a JSON string
        json_string = json.dumps(new_gm['validation_schema'])
        # Clear the existing content in the validation schema element
        validation_schema.clear()
        # Send the JSON string to the validation schema element
        validation_schema.send_keys(json_string)
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the element was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Generic mode element added successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        # Go to Optical Element Groups page and return ID of the newly created group
        driver.get(f"{BASE_URL}/admin/hardware/genericmode/")
        # Initialize lists to store extracted IDs
        ids = []
        # Find all rows in the table body
        rows = driver.find_elements(By.XPATH, "//table[@id='result_list']/tbody/tr")    
        # Loop through each row and extract ID
        for row in rows:
            # Extract the ID (from the <input> tag inside <td class="action-checkbox">)
            id_element = row.find_element(By.XPATH, ".//td[@class='action-checkbox']/input")
            ids.append(int(id_element.get_attribute("value")))
        # Get generic mode ID
        sorted_ids = sorted(ids)
        new_gm_id = sorted_ids[-1]
        print (f"New genericmode with 'id = {new_gm_id}' was successfully created.")
        driver.quit()
        return new_gm_id        
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return None


def login_and_create_GMG(BASE_URL, USERNAME, PASSWORD, new_gmg):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")         
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/genericmodegroup/add/")
        print("Accessed generic mode group form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------       
        instrument_type_field = driver.find_element(By.ID, 'id_instrument_type')       
        all_instrument_type_options = [option.text for option in instrument_type_field.find_elements(By.TAG_NAME, 'option')]
        my_instrument_type = new_gmg['instrument_type']      
        for option in instrument_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text == my_instrument_type:
                option.click()
                break       
        if my_instrument_type not in all_instrument_type_options:
            print ("Unable to create generic mode group with the instrument type '" + my_instrument_type + "' because that "\
                   "instrument type doesn't exist among the existing instrument types ['" + "', '".join(all_instrument_type_options[1:]) + "']")
            driver.quit()
            return None
        #------------------------------------------------------------------------------------------------------------------------       
        mode_type_field = driver.find_element(By.ID, 'id_type')
        all_mode_type_options = [option.text for option in mode_type_field.find_elements(By.TAG_NAME, 'option')]     
        my_mode_type = new_gmg['type']       
        for option in mode_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text == my_mode_type:
                option.click()
                break      
        if my_mode_type not in all_mode_type_options:
            print ("Unable to create generic mode group with the mode type '" + my_instrument_type + "' because that "\
                   "mode type doesn't exist among the existing mode types ['" + "', '".join(all_mode_type_options[1:]) + "']")
            driver.quit()
            return None
        #------------------------------------------------------------------------------------------------------------------------    
        modes_type_field = driver.find_element(By.ID, 'id_modes')
        my_modes_list = [e['code'] + ': ' + e['name'] for e in new_gmg['modes']]      
        for option in modes_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text in my_modes_list:
                option.click()
        all_modes_type = [option.text for option in modes_type_field.find_elements(By.TAG_NAME, 'option')] 
        non_existing_elements = []     
        for my_option in my_modes_list:
            if my_option not in all_modes_type:
                print ("Unable to add generic mode to the generic mode group because generic mode '" + my_option + "' doesn't exist "\
                       "among the existing generic modes ['" + "', '".join(all_modes_type) + "']")
                non_existing_elements.append(my_option)       
        if non_existing_elements == my_modes_list:
            print ('No generic modes to add to the generic mode group. Generic mode group will not be created.')
            driver.quit()
            return None
        #------------------------------------------------------------------------------------------------------------------------
        if new_gmg['default'] != {}: 
            default_field = driver.find_element(By.ID, 'id_default')
            my_default = new_gmg['default']['code'] + ': ' + new_gmg['default']['name']
            added_modes = [e for e in my_modes_list if e not in non_existing_elements]          
            if my_default in added_modes:
                for option in default_field.find_elements(By.TAG_NAME, 'option'):
                    if option.text == my_default:
                        option.click()
                        break                
            else:                
                print ("Unable to set default generic mode for the generic mode group because that mode '" + my_default + "' "\
                       "doesn't exist among the added modes ['" + "', '".join(added_modes) + "'] for this group.")
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the gorup was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Generic mode group added successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        # Go to Generic Mode Groups page and return ID of the newly created group
        driver.get(f"{BASE_URL}/admin/hardware/genericmodegroup/")
        # Initialize lists to store extracted IDs
        ids = []
        # Find all rows in the table body
        rows = driver.find_elements(By.XPATH, "//table[@id='result_list']/tbody/tr")    
        # Loop through each row and extract ID
        for row in rows:
            # Extract the ID (from the <input> tag inside <td class="action-checkbox">)
            id_element = row.find_element(By.XPATH, ".//td[@class='action-checkbox']/input")
            ids.append(int(id_element.get_attribute("value")))
        # Get generic mode ID
        sorted_ids = sorted(ids)
        new_gmg_id = sorted_ids[-1]
        print (f"New genericmodegroup with 'id = {new_gmg_id}' was successfully created.")
        driver.quit()
        return new_gmg_id
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return None


def retrieve_component(BASE_URL, COMPONENT, component_id, filters=None):
    """
    Retrieve details of a specific component.

    Args:
        BASE_URL: Base URL of your ConfigDB.
        COMPONENT: Possible ConfigDB component.
        component_id (int): ID of the component.
        filters (dict, optional): Optional query parameters for filtering.

    Returns:
        dict: Component details or error message.
    """
    endpoint = f'{BASE_URL}/{COMPONENT}/{component_id}/'
    response = requests.get(endpoint, params=filters)
    print(f"Status Code --> [{response.status_code} : {response.reason}]")
    if response.status_code == 200:
        json_response = response.json()
        print (f"Specified {COMPONENT[:-1]} with 'id = {component_id}' was successfully retrieved.")
        return json_response
    else:
        print (f"Failed to retrieve specifed {COMPONENT[:-1]} with 'id = {component_id}'.")
        return {}


def update_component(BASE_URL, COMPONENT, AUTHORIZATION_TOKEN, component_id, component_update, filters=None):
    """
    Updates a component using the provided API endpoint.

    Args:
        BASE_URL: Base URL of your ConfigDB.
        COMPONENT: Possible ConfigDB component.
        AUTHORIZATION_TOKEN: Authorization token (super-user or local configDB token).
        component_id (int): The ID of the component to update.
        component_update (dict): The JSON payload containing the updated fields.
        filters (dict, optional): Optional query parameters for filtering.

    Returns:
        dict: Updated component details or error message.
    """
    endpoint = f"{BASE_URL}/{COMPONENT}/{component_id}/"
    headers = {"Authorization": f"Token {AUTHORIZATION_TOKEN}"}
    response = requests.put(endpoint, params=filters, data=component_update, headers=headers)
    print(f"Status Code --> [{response.status_code} : {response.reason}]")
    if response.status_code == 200:
        json_response = response.json()
        print (f"Specified {COMPONENT[:-1]} with 'id = {component_id}' was successfully updated.")
        return json_response
    else:
        print(f"Failed to update specifed {COMPONENT[:-1]} with 'id = {component_id}'.")
        return {}


def login_and_update_OEG(BASE_URL, USERNAME, PASSWORD, oeg_id, update_oeg):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/opticalelementgroup/{oeg_id}/change/")
        print(f"Accessed optical element group with 'id = {oeg_id}'")     
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        name_field = driver.find_element(By.NAME, 'name')
        # Clear the field first
        name_field.clear()
        name_field.send_keys(update_oeg['name'])
        #------------------------------------------------------------------------------------------------------------------------
        type_field = driver.find_element(By.NAME, 'type')
        # Clear the field first
        type_field.clear()
        type_field.send_keys(update_oeg['type'])
        #------------------------------------------------------------------------------------------------------------------------
        # Select multiple options
        optical_elements_field = driver.find_element(By.ID, 'id_optical_elements')
        # Use JavaScript to clear all selections
        driver.execute_script(
                              """
                              var select = arguments[0];
                              for (var i = 0; i < select.options.length; i++) 
                              {
                               select.options[i].selected = false;  // Deselect each option
                              }
                              """, 
                              optical_elements_field
                             )
        my_list_of_optical_elements = [e['name'] for e in update_oeg['optical_elements']]        
        for option in optical_elements_field.find_elements(By.TAG_NAME, 'option'):
            if option.text in my_list_of_optical_elements:
                option.click()
        #------------------------------------------------------------------------------------------------------------------------
        all_optical_elements_options = [option.text for option in optical_elements_field.find_elements(By.TAG_NAME, 'option')]
        non_existing_elements = []
        for my_option in my_list_of_optical_elements:
            if my_option not in all_optical_elements_options:
                print ("Unable to update optical element group with the optical element '" + my_option + "' because it doesn't exist in the configDB.")
                non_existing_elements.append(my_option)
        #------------------------------------------------------------------------------------------------------------------------
        if non_existing_elements == my_list_of_optical_elements:
            print ('No optical elements were updated in the optical element group.')
            driver.quit()
            return False      
        #------------------------------------------------------------------------------------------------------------------------
        overhead_field = driver.find_element(By.NAME, 'element_change_overhead')
        # Clear the field first
        overhead_field.clear()
        # Send the value
        overhead_field.send_keys(update_oeg['element_change_overhead'])
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()       
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/opticalelementgroup/{oeg_id}/change/")
        #------------------------------------------------------------------------------------------------------------------------
        default_elements_field = driver.find_element(By.ID, 'id_default')
        # Use JavaScript to clear all selections
        driver.execute_script(
                              """
                              var select = arguments[0];
                              for (var i = 0; i < select.options.length; i++) 
                              {
                               select.options[i].selected = false;  // Deselect each option
                              }
                              """, 
                              default_elements_field
                             )
        if 'default' in list(update_oeg.keys()):    
            my_default_element = update_oeg['default']['name']           
            my_list_of_optical_elements_new = [e for e in my_list_of_optical_elements if e not in non_existing_elements]         
            if my_default_element in my_list_of_optical_elements_new:              
                for option in default_elements_field.find_elements(By.TAG_NAME, 'option'):
                    if option.text == my_default_element:
                        option.click()
                        break        
            else:               
                print ("Unable to set default element with the name '" + my_default_element + "' because it doesn't "\
                       "exist among the added optical elements ['" + "', '".join(my_list_of_optical_elements_new) + "'] for this group.")
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the group was updated successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print (f"Optical element group with 'id = {oeg_id}' was successfully updated.")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return True
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return False


def login_and_update_GM(BASE_URL, USERNAME, PASSWORD, gm_id, update_gm):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/genericmode/{gm_id}/change/")
        print(f"Accessed generic mode element with 'id = {gm_id}'") 
        # Update fields
        #------------------------------------------------------------------------------------------------------------------------
        name_field = driver.find_element(By.ID, 'id_name')
        # Clear the field first
        name_field.clear()
        name_field.send_keys(update_gm['name'])
        #------------------------------------------------------------------------------------------------------------------------
        code_field = driver.find_element(By.ID, 'id_code')
        # Clear the field first
        code_field.clear()
        code_field.send_keys(update_gm['code'])
        #------------------------------------------------------------------------------------------------------------------------
        overhead_field = driver.find_element(By.ID, 'id_overhead')
        # Clear the field first
        overhead_field.clear()
        # Send the value
        overhead_field.send_keys(update_gm['overhead'])
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the checkbox element
        checkbox = driver.find_element(By.ID, 'id_schedulable')
        # Check if the checkbox is already in the desired state
        checkbox_state = update_gm['schedulable']
        if checkbox_state != checkbox.is_selected():
            checkbox.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the validation schema element
        validation_schema = driver.find_element(By.ID, "id_validation_schema")
        # Convert the dictionary to a JSON string
        json_string = json.dumps(update_gm['validation_schema'])
        # Clear the existing content in the validation schema element
        validation_schema.clear()
        # Send the JSON string to the validation schema element
        validation_schema.send_keys(json_string)
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the generic mode element was updated successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print (f"Generic mode element with 'id = {gm_id}' was successfully updated.")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return True     
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return False


def login_and_update_GMG(BASE_URL, USERNAME, PASSWORD, gmg_id, update_gmg):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")         
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/genericmodegroup/{gmg_id}/change/")
        print("Accessed generic mode group form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        instrument_type_field = driver.find_element(By.ID, 'id_instrument_type')
        # Use JavaScript to clear all selections
        driver.execute_script(
                              """
                              var select = arguments[0];
                              for (var i = 0; i < select.options.length; i++) 
                              {
                               select.options[i].selected = false;  // Deselect each option
                              }
                              """, 
                              instrument_type_field
                             )
        all_instrument_type_options = [option.text for option in instrument_type_field.find_elements(By.TAG_NAME, 'option')]
        my_instrument_type = update_gmg['instrument_type']      
        for option in instrument_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text == my_instrument_type:
                option.click()
                break   
        if my_instrument_type not in all_instrument_type_options:
            print ("Unable to update generic mode group with the instrument type '" + my_instrument_type + "' because that "\
                   "instrument type doesn't exist among the existing instrument types ['" + "', '".join(all_instrument_type_options[1:]) + "']")
            driver.quit()
            return False
        #------------------------------------------------------------------------------------------------------------------------       
        mode_type_field = driver.find_element(By.ID, 'id_type')       
        # Use JavaScript to clear all selections
        driver.execute_script(
                              """
                              var select = arguments[0];
                              for (var i = 0; i < select.options.length; i++) 
                              {
                               select.options[i].selected = false;  // Deselect each option
                              }
                              """, 
                              mode_type_field
                             )     
        all_mode_type_options = [option.text for option in mode_type_field.find_elements(By.TAG_NAME, 'option')]      
        my_mode_type = update_gmg['type']              
        for option in mode_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text == my_mode_type:
                option.click()
                break      
        if my_mode_type not in all_mode_type_options:
            print ("Unable to update generic mode group with the mode type '" + my_instrument_type + "' because that "\
                   "mode type doesn't exist among the existing mode types ['" + "', '".join(all_mode_type_options[1:]) + "']")
            driver.quit()
            return False
        #------------------------------------------------------------------------------------------------------------------------    
        modes_type_field = driver.find_element(By.ID, 'id_modes')      
        # Use JavaScript to clear all selections
        driver.execute_script(
                              """
                              var select = arguments[0];
                              for (var i = 0; i < select.options.length; i++) 
                              {
                               select.options[i].selected = false;  // Deselect each option
                              }
                              """, 
                              modes_type_field
                             )
        my_modes_list = [e['code'] + ': ' + e['name'] for e in update_gmg['modes']]         
        for option in modes_type_field.find_elements(By.TAG_NAME, 'option'):
            if option.text in my_modes_list:
                option.click()    
        all_modes_type = [option.text for option in modes_type_field.find_elements(By.TAG_NAME, 'option')] 
        non_existing_elements = []     
        for my_option in my_modes_list:
            if my_option not in all_modes_type:
                print ("Unable to update generic mode group with generic mode '" + my_option + "' because that mode doesn't exist "\
                       "among the existing generic modes ['" + "', '".join(all_modes_type) + "']")
                non_existing_elements.append(my_option)       
        if non_existing_elements == my_modes_list:
            print ('No generic modes to update the generic mode group. Generic mode group will not be updated.')
            driver.quit()
            return False
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()      
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/genericmodegroup/{gmg_id}/change/")
        #------------------------------------------------------------------------------------------------------------------------
        if update_gmg['default'] != {}:          
            default_field = driver.find_element(By.ID, 'id_default')         
            # Use JavaScript to clear all selections
            driver.execute_script(
                                  """
                                  var select = arguments[0];
                                  for (var i = 0; i < select.options.length; i++) 
                                  {
                                   select.options[i].selected = false;  // Deselect each option
                                  }
                                  """, 
                                  default_field
                                 )
            my_default = update_gmg['default']['code'] + ': ' + update_gmg['default']['name']
            added_modes = [e for e in my_modes_list if e not in non_existing_elements]          
            if my_default in added_modes:
                for option in default_field.find_elements(By.TAG_NAME, 'option'):
                    if option.text == my_default:
                        option.click()
                        break                
            else:                
                print ("Unable to update default generic mode for this generic mode group because that mode '" + my_default + "' "\
                       "doesn't exist among the updated modes ['" + "', '".join(added_modes) + "'] for this group.")
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the gorup was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print (f"Generic mode group with 'id = {gmg_id}' was successfully updated.")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return True
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return False


def destroy_component(BASE_URL, COMPONENT, AUTHORIZATION_TOKEN, component_id, filters=None):
    """
    Delete a specific component.

    Args:
        BASE_URL: Base URL of your ConfigDB.
        COMPONENT: Possible ConfigDB component.
        AUTHORIZATION_TOKEN: Authorization token (super-user or local configDB token).
        component_id (int): ID of the component.
        filters (dict, optional): Optional query parameters for filtering.

    Returns:
        prints out message about deleted component or error message.
    """
    endpoint = f'{BASE_URL}/{COMPONENT}/{component_id}/'
    headers = {"Authorization": f"Token {AUTHORIZATION_TOKEN}"}
    response = requests.delete(endpoint, params=filters, headers=headers)
    print(f"Status Code --> [{response.status_code} : {response.reason}]")
    if response.status_code == 204:
        print (f"Specified {COMPONENT[:-1]} with 'id = {component_id}' was successfully deleted.")
    else:
        print (f"Failed to delete specified {COMPONENT[:-1]} with 'id = {component_id}'.")

I hope this can be helpful.

Best regards,
Nikola

@nebeskimehanicar
Copy link
Author

Regarding Mode Types, I wrote a python code for creating, updating, destroying, and listing mode types using the Selenium web-driver. See the code below:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Jan 2025

@author: nikola knezevic AOB
"""

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options


# Base URL
BASE_URL = "http://127.0.0.1:7000"

# Login credentials
USERNAME = "test_user"
PASSWORD = "test_pass"


#---------------------------------------------------------
def list_MT():
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/")
        print("Accessed mode type form.")
        # Locate the rows in the table body
        rows = driver.find_elements(By.CSS_SELECTOR, "table#result_list tbody tr")
        # Initialize a list to store extracted data
        data = []
        # Loop through each row and extract required information
        for row in rows:
            # Extract the 'id' from the checkbox value
            row_id = row.find_element(By.CSS_SELECTOR, "td.action-checkbox input").get_attribute("value")
            # Append to the data list
            data.append({"id": row_id})
        # Print the extracted data
        print ('Mode type IDs:')
        for entry in data:
            print(entry)
        driver.quit()
        return data
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return data
#---------------------------------------------------------
def login_and_create_MT(new_mt):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")         
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/add/")
        print("Accessed mode type form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        id_field = driver.find_element(By.ID, 'id_id')
        # Send the value
        id_field.send_keys(new_mt['id'])
        #------------------------------------------------------------------------------------------------------------------------
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the gorup was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Mode type added successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return new_mt['id']
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return None
#---------------------------------------------------------
def login_and_update_MT(mt_id, update_mt):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")         
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/{mt_id}/change/")
        print("Accessed mode type form.")
        """
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        id_field = driver.find_element(By.ID, 'id_id')
        # Clear the field first
        id_field.clear()
        # Send the value
        id_field.send_keys(update_mt['id'])
        #------------------------------------------------------------------------------------------------------------------------
        """
        #########################################################################################################################
        # Locate the "Delete" link using its class
        delete_link = driver.find_element(By.CLASS_NAME, "deletelink")
        # Click on the "Delete" link
        delete_link.click()
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/{mt_id}/delete/")
        # Locate the "Yes, I'm sure" button using its value attribute
        yes_button = driver.find_element(By.XPATH, '//input[@value="Yes, I’m sure"]')
        # Click the "Yes, I’m sure" button
        yes_button.click()
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/add/")
        # Locate 'Id' field
        id_field = driver.find_element(By.ID, 'id_id')
        # Send the value
        id_field.send_keys(update_mt['id'])
        #########################################################################################################################
        # Submit the form
        save_button = driver.find_element(By.NAME, '_save')
        save_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the gorup was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Mode type updated successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return True
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return False
#---------------------------------------------------------
def login_and_destroy_MT(mt_id):
    # Set up Chrome options for headless mode
    chrome_options = Options()
    # Run Chrome in headless mode
    chrome_options.add_argument("--headless")
    # Prevents rendering issues in older systems
    chrome_options.add_argument("--disable-gpu")
    # Useful options for containerized environments like Docker
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    # Set up the WebDriver service
    driver = webdriver.Chrome(options=chrome_options)
    try:
        # Open the login page
        driver.get(f"{BASE_URL}/admin/login/?next=/admin/")
        print("Accessed login page.")
        # Log in
        username_field = driver.find_element(By.NAME, 'username')
        password_field = driver.find_element(By.NAME, 'password')
        username_field.send_keys(USERNAME)
        password_field.send_keys(PASSWORD)
        login_button = driver.find_element(By.XPATH, '//input[@type="submit"]')
        login_button.click()
        # Check if login was successful
        WebDriverWait(driver, 10).until(EC.title_contains("Site administration"))
        print("Login successful: OK")         
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/{mt_id}/change/")
        print("Accessed mode type form.")
        # Fill in the fields
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the "Delete" link using its class
        delete_link = driver.find_element(By.CLASS_NAME, "deletelink")
        # Click on the "Delete" link
        delete_link.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Navigate to the form page and interact with it
        driver.get(f"{BASE_URL}/admin/hardware/modetype/{mt_id}/delete/")
        print("Accessed mode type delete form.")
        #------------------------------------------------------------------------------------------------------------------------
        # Locate the "Yes, I'm sure" button using its value attribute
        yes_button = driver.find_element(By.XPATH, '//input[@value="Yes, I’m sure"]')
        # Click the "Yes, I’m sure" button
        yes_button.click()
        #------------------------------------------------------------------------------------------------------------------------
        # Check if the gorup was added successfully
        success_message = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'success')))
        if success_message:
            print("Mode type deleted successfully: OK")
        #------------------------------------------------------------------------------------------------------------------------
        driver.quit()
        return True
    except Exception as e:
        print(f"An error occurred: {e}")
        driver.quit()
        return False
#---------------------------------------------------------


"""
tm_list = list_MT()
"""

"""
new_mt = {'id': 'guiding new'}
mt_id = login_and_create_MT(new_mt)
"""

"""
mt_id = 'guiding new'
update_mt = {'id': 'guiding new 2'}
updated_mt = login_and_update_MT(mt_id, update_mt)
"""

"""   
mt_id = 'guiding new 2'
destroyed_mt = login_and_destroy_MT(mt_id)
"""

I want to add that I found a problem when you want to change/update the mode type.
Whenever you change the mode type and save it, it just automatically creates a new mode type based on your update, but the old one remains. So I did a workaround in the script above to avoid that problem.

Let me know if something is unclear.

Cheers.

@nebeskimehanicar
Copy link
Author

BTW, I realize I reported these issues from a different GitHub account than the previous ones, sorry for that :)

@jnation3406
Copy link
Member

Thanks for reporting this, and sorry you had to go through the trouble of writing that selenium stuff just to set these values via the API! I will add this to the list of things to fix when I work on it - the goal is for everything to be accessible from the API.

@jnation3406
Copy link
Member

I have a PR in review on configdb which should address this:

observatorycontrolsystem/configdb#50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants