🏡 index : quine-global/quine-anaconda-webui.git

# Copyright (C) 2025 Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later

import os
import sys

HELPERS_DIR = os.path.dirname(__file__)
sys.path.append(HELPERS_DIR)

from steps import SOFTWARE_SELECTION

PAYLOADS_SERVICE = "org.fedoraproject.Anaconda.Modules.Payloads"
PAYLOADS_INTERFACE = PAYLOADS_SERVICE
PAYLOADS_OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Payloads"

PAYLOAD_DNF_INTERFACE = "org.fedoraproject.Anaconda.Modules.Payloads.Payload.DNF"


class PayloadDNFDBus():
    def __init__(self, machine):
        self.machine = machine
        self._bus_address = self.machine.execute("cat /run/anaconda/bus.address")

    def _get_active_payload(self):
        """Get the active payload object path."""
        ret = self.machine.execute(
            f'busctl --address="{self._bus_address}" '
            f'get-property '
            f'{PAYLOADS_SERVICE} '
            f'{PAYLOADS_OBJECT_PATH} '
            f'{PAYLOADS_INTERFACE} ActivePayload'
        )
        return ret.split('s ')[1].strip().strip('"')

    def dbus_set_packages_selection(self, environment):
        """Set the packages selection via D-Bus.

        :param environment: environment ID to set
        """
        payload_path = self._get_active_payload()

        # Build the structure for busctl: a{sv} (dictionary of string to variant)
        # Format: a{sv} N "key1" s "value1" "key2" as N "value2_1" ...
        # For empty array, use "as 0"
        # Structure: a{sv} 2 "environment" s "server-product-environment" "groups" as 0
        self.machine.execute(
            f'busctl --address="{self._bus_address}" '
            f'set-property '
            f'{PAYLOADS_SERVICE} '
            f'{payload_path} '
            f'{PAYLOAD_DNF_INTERFACE} '
            f'PackagesSelection '
            f'a{{sv}} 2 "environment" s "{environment}" "groups" as 0'
        )

    def dbus_reset_to_default_environment(self, environment="server-product-environment"):
        """Reset packages selection to default environment with empty groups.

        :param environment: environment ID to set (default: server-product-environment)
        """
        self.dbus_set_packages_selection(environment)


class PayloadDNF():
    def __init__(self, browser):
        self.browser = browser
        self._step = SOFTWARE_SELECTION

    def check_selected_environment(self, environment):
        env_id = f"{self._step}-environment-{environment}"
        self.browser.wait_visible(f"#{env_id}.pf-m-selected")

    def select_environment(self, environment):
        env_id = f"{self._step}-environment-{environment}"
        self.browser.click(f"#{env_id}")
        self.browser.wait_visible(f"#{env_id}.pf-m-selected")

    def check_not_selected_group(self, group):
        """Check that the specified groups are not selected."""
        group_id = f"{self._step}-group-{group}"
        self.browser.wait_visible(f"#{group_id}:not(.pf-m-selected)")

    def check_group_selected(self, group):
        """Check if a specific group is selected."""
        group_id = f"{self._step}-group-{group}"
        self.browser.wait_visible(f"#{group_id}.pf-m-selected")

    def select_group(self, group):
        """Select a group by clicking on it."""
        group_id = f"{self._step}-group-{group}"
        self.browser.click(f"#{group_id}")
        self.check_group_selected(group)

    def check_first_optional_group(self, group):
        """Check that a specific group is the first item in the optional groups menu."""
        optional_groups_id = f"{self._step}-optional-groups"
        group_id = f"{self._step}-group-{group}"
        # Check that the optional groups menu exists
        self.browser.wait_visible(f"#{optional_groups_id} li:first-of-type #{group_id}")