#!/usr/bin/python3## Copyright (C) 2025 Red Hat, Inc.# SPDX-License-Identifier: LGPL-2.1-or-laterimport datetimefrom zoneinfo import ZoneInfofrom anacondalib import VirtInstallMachineCasefrom installer import Installerfrom language import Languagefrom review import Reviewfrom testlib import nondestructive, test_mainfrom timezone import DateAndTime@nondestructiveclass TestDateAndTime(VirtInstallMachineCase):def setUp(self):super().setUp()def testDefaultState(self):"""Description:Test default state picked up from backendExpected results:- WebUI auto date/time and timezone matches backend- NTP, timezone, date and time match backend- The selected timezone is displayed in the Review screen"""b = self.browserm = self.machinei = Installer(b, m)r = Review(b, m)dt = DateAndTime(b, m)default_timezone = dt.dbus_get_timezone()i.open()i.reach(i.steps.DATE_TIME)dt.check_auto_date_time(dt.dbus_get_ntp_enabled())dt.check_auto_timezone(True)region, city = default_timezone.split('/', 1)dt.check_region(region)dt.check_city(city)i.reach(i.steps.REVIEW)r.check_timezone(default_timezone)def testNtpServerSelection(self):"""Description:Test selecting custom NTP server.Expected Results:- The default NTP servers are loaded from the chronyd configuration- The user can configure a custom NTP server in the UI"""b = self.browserm = self.machinei = Installer(b, m)dt = DateAndTime(b, m)i.open()i.reach(i.steps.DATE_TIME)dt.set_auto_date_time(True)dt.dbus_clear_time_sources()b.click(f"#{i.steps.DATE_TIME}-configure-ntp")dt.check_ntp_server_enabled("2.fedora.pool.ntp.org", 0)dt.add_ntp_server("europe.pool.ntp.org", 1)def testManualDateTimeTimezoneAndFormat(self):"""Description:Test manual setting of time, date, timezone and time format.Expected results:- Time and date are manually set and reflected in backend- Manual timezone selection changes timezone on backend- Switching between 24h and AM/PM format works as expected"""b = self.browserm = self.machinei = Installer(b, m)dt = DateAndTime(b, m)lang = Language(b, m)i.open()lang.select_locale("de_DE")i.reach(i.steps.DATE_TIME)dt.set_auto_date_time(False)dt.set_date("2025-01-01")dt.set_time("19:00")dt.check_date("2025-01-01")dt.check_time("19:00")dt.set_time_format("ampm")dt.check_time_format("ampm")dt.check_time("07:00 PM")dt.set_time_format("24")dt.check_time_format("24")dt.check_time("19:00")dt.set_auto_timezone(False)dt.select_region("America")dt.select_city("Sao_Paulo")dt.check_timezone_label("GMT-3, UTC-3")self.assertEqual(dt.dbus_get_timezone(), "America/Sao_Paulo")# Test timezone with multiple cities (same region)dt.select_city("Argentina/Buenos_Aires")dt.check_timezone_label("GMT-3, UTC-3")self.assertEqual(dt.dbus_get_timezone(), "America/Argentina/Buenos_Aires")def testTimezoneAndTimeFormat(self):"""Description:Test full cycle of setting time zone, time format (24h/AMPM), date/time,and verify correct UTC conversion on the backend.Expected results:- User can manually disable automatic time and timezone settings.- Time format can be switched between 24h and AM/PM, and is correctly reflected in the UI.- Timezone selection (e.g., America/New_York, Asia/Tokyo) updates both the label and backend value.- The backend datetime is correctly calculated and stored in UTC regardless of selected timezone.- Setting local time in one timezone correctly adjusts backend UTC time."""b = self.browserm = self.machinei = Installer(b, m)dt = DateAndTime(b, m)i.open()i.reach(i.steps.DATE_TIME)dt.set_auto_date_time(False)dt.set_auto_timezone(False)dt.set_time_format("24")dt.check_time_format("24")dt.select_region("America")dt.select_city("New_York")self.assertEqual(dt.dbus_get_timezone(), "America/New_York")dt.set_date("2025-01-31")dt.set_time("15:45")dt.set_time_format("ampm")dt.check_time_format("ampm")dt.check_time("03:45 PM")dt.set_time_format("24")dt.check_time_format("24")dt.check_time("15:45")backend_iso = dt.dbus_get_system_datetime()dt_parsed = datetime.datetime.fromisoformat(backend_iso)dt_utc = dt_parsed.astimezone(datetime.timezone.utc)expected_utc = datetime.datetime(2025, 1, 31, 20, 45, tzinfo=datetime.timezone.utc)assert dt_utc.strftime("%Y-%m-%dT%H:%M") == expected_utc.strftime("%Y-%m-%dT%H:%M")dt.select_region("Asia")dt.select_city("Tokyo")self.assertEqual(dt.dbus_get_timezone(), "Asia/Tokyo")dt.check_time("05:45")dt.set_time("00:45")dt.set_time_format("ampm")dt.check_time_format("ampm")dt.check_time("12:45 AM")dt.set_time_format("24")dt.check_time_format("24")dt.set_time("08:00")local_tokyo = datetime.datetime(2025, 2, 1, 8, 0, tzinfo=ZoneInfo("Asia/Tokyo"))backend_iso3 = dt.dbus_get_system_datetime()self.assertTrue(backend_iso3.startswith(local_tokyo.strftime("%Y-%m-%dT%H:%M")),f"Expected backend local time {local_tokyo}, got {backend_iso3}")if __name__ == '__main__':test_main()