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

# Copyright (C) 2021 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 step_logger import log_step
from steps import LANGUAGE
from testlib import wait

LOCALIZATION_SERVICE = "org.fedoraproject.Anaconda.Modules.Localization"
LOCALIZATION_INTERFACE = "org.fedoraproject.Anaconda.Modules.Localization"
LOCALIZATION_OBJECT_PATH = "/org/fedoraproject/Anaconda/Modules/Localization"

BOSS_SERVICE = "org.fedoraproject.Anaconda.Boss"
BOSS_INTERFACE = BOSS_SERVICE
BOSS_OBJECT_PATH = "/org/fedoraproject/Anaconda/Boss"


class Locale():
    def __init__(self, browser, machine):
        self.browser = browser
        self.machine = machine
        self._step = LANGUAGE
        self._language_search = f".{self._step}-language-search .pf-v6-c-text-input-group__text-input"

    @log_step()
    def select_locale(self, locale, locale_name=None, is_common=True):
        common_prefix = "common" if is_common else "alpha"
        if self.browser.val(self._language_search) != "":
            self.input_locale_search("")

        if locale_name:
            self.input_locale_search(locale_name)

        self.browser.click(f"#{self._step}-language-option-{common_prefix}-{locale}")
        self.check_selected_locale(locale, is_common)

    @log_step()
    def get_locale_search(self):
        return self.browser.val(self._language_search)

    @log_step()
    def input_locale_search(self, text):
        self.browser.set_input_text(self._language_search, text)

    @log_step()
    def locale_option_visible(self, locale, visible=True, is_common=True):
        common_prefix = "common" if is_common else "alpha"
        if visible:
            self.browser.wait_visible(f"#{self._step}-language-option-{common_prefix}-{locale}")
        else:
            self.browser.wait_not_present(f"#{self._step}-language-option-{common_prefix}-{locale}")

    @log_step(snapshot_before=True)
    def check_selected_locale(self, locale, is_common=True):
        common_prefix = "common" if is_common else "alpha"
        web_locale = locale.replace("_", "-").lower()
        self.browser.wait_visible(f"#{self._step}-language-option-{common_prefix}-{locale}.pf-m-selected [lang='{web_locale}']")

class Keyboard():
    def __init__(self, browser, machine):
        self.browser = browser
        self.machine = machine
        self._step = LANGUAGE
        self._keyboard_search = f".{self._step}-keyboard-search .pf-v6-c-text-input-group__text-input"

    def select_keyboard(self, keyboard, keyboard_name=None, is_common=True):
        self.browser.click(f"#{self._step}-change-system-keyboard-layout-modal-open-button")
        self.browser.wait_visible(f"#{self._step}-change-system-keyboard-layout-modal")

        common_prefix = "common" if is_common else "alpha"
        if self.browser.val(self._keyboard_search) != "":
            self.input_keyboard_search("")

        if keyboard_name:
            self.input_keyboard_search(keyboard_name)

        self.browser.click(f"#{self._step}-keyboard-option-{common_prefix}-{keyboard}")
        self.browser.click(f"#{self._step}-change-system-keyboard-layout-modal-save-button")
        self.browser.wait_not_present(f"#{self._step}-change-system-keyboard-layout-modal")

    def input_keyboard_search(self, text):
        self.browser.set_input_text(self._keyboard_search, text)

    def check_selected_keyboard(self, keyboard, is_common=True, present=True):
        if present:
            self.browser.wait_in_text("p", keyboard)
        else:
            self.browser.wait_not_present(f"p:contains('{keyboard}')")

    def _check_selected_keyboards_on_device(self, expected_layouts, expected_variants=None):
        result = self.machine.execute("localectl status")
        layout = None
        variant = None

        for line in result.splitlines():
            if "X11 Layout" in line:
                layout = line.split(":")[-1].strip()
            if "X11 Variant" in line:
                variant = line.split(":")[-1].strip()

        # Convert comma-separated string to list
        actual_layouts = [l.strip() for l in layout.split(",")] if layout else []
        actual_variants = [v.strip() for v in variant.split(",")] if variant else []

        # Convert expected_layouts to list if it's a string
        if isinstance(expected_layouts, str):
            expected_layouts = [expected_layouts]
        if expected_variants and isinstance(expected_variants, str):
            expected_variants = [expected_variants]

        assert actual_layouts == expected_layouts, f"Expected layouts {expected_layouts}, but got {actual_layouts}"

        try:
            if expected_variants:
                assert actual_variants == expected_variants, f"Expected variants {expected_variants}, but got {actual_variants}"
            else:
                assert not actual_variants, f"Expected no variants, but got {actual_variants}"
        except AssertionError:
            # Try one more time for rubustness
            self.check_selected_keyboards_on_device(expected_layouts, expected_variants)

    def check_selected_keyboards_on_device(self, expected_layouts, expected_variants=None):
        def wrapped_check():
            try:
                self._check_selected_keyboards_on_device(expected_layouts, expected_variants)
                return True
            except AssertionError:
                return False

        wait(wrapped_check)


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

    def dbus_set_language(self, value):
        self.machine.execute(f'dbus-send --print-reply --bus="{self._bus_address}" \
            --dest={LOCALIZATION_INTERFACE} \
            {LOCALIZATION_OBJECT_PATH} \
            org.freedesktop.DBus.Properties.Set \
            string:"{LOCALIZATION_INTERFACE}" string:"Language" variant:string:"{value}"')

    def dbus_get_language(self):
        return self.machine.execute(f'dbus-send --print-reply --bus="{self._bus_address}" \
            --dest={LOCALIZATION_INTERFACE} \
            {LOCALIZATION_OBJECT_PATH} \
            org.freedesktop.DBus.Properties.Get \
            string:"{LOCALIZATION_INTERFACE}" string:"Language"')

    def dbus_set_locale(self, value):
        self.machine.execute(f'busctl --address="{self._bus_address}" \
            call \
            {BOSS_SERVICE} \
            {BOSS_OBJECT_PATH} \
            {BOSS_INTERFACE} SetLocale s "{value}"')

    def dbus_set_compositor_layouts(self, layouts):
        self.machine.execute(f"busctl --address='{self._bus_address}' \
            call \
            {LOCALIZATION_SERVICE} \
            {LOCALIZATION_OBJECT_PATH} \
            {LOCALIZATION_INTERFACE} SetCompositorLayouts asas 1 '{layouts[0]}' 0")

    def dbus_reset_xlayouts(self):
        self.machine.execute(f'busctl --address="{self._bus_address}" \
            set-property \
            {LOCALIZATION_SERVICE} \
            {LOCALIZATION_OBJECT_PATH} \
            {LOCALIZATION_INTERFACE} XLayouts as 0')

    def dbus_reset_virtual_console_keymap(self):
        self.machine.execute(f'busctl --address="{self._bus_address}" \
            set-property \
            {LOCALIZATION_SERVICE} \
            {LOCALIZATION_OBJECT_PATH} \
            {LOCALIZATION_INTERFACE} VirtualConsoleKeymap s ""')

    def dbus_get_language_kickstarted(self):
        out = self.machine.execute(f'busctl --address="{self._bus_address}" \
            get-property \
            {LOCALIZATION_SERVICE} \
            {LOCALIZATION_OBJECT_PATH} \
            {LOCALIZATION_INTERFACE} LanguageKickstarted')
        return "true" in out


class Language(Locale, Keyboard, LanguageDBus):
    def __init__(self, browser, machine):
        Locale.__init__(self, browser, machine)
        Keyboard.__init__(self, browser, machine)
        LanguageDBus.__init__(self, machine)