#!/usr/bin/python3 # # Copyright (C) 2025 Red Hat, Inc. # SPDX-License-Identifier: LGPL-2.1-or-later import datetime from zoneinfo import ZoneInfo from anacondalib import VirtInstallMachineCase from installer import Installer from language import Language from review import Review from testlib import nondestructive, test_main from timezone import DateAndTime @nondestructive class TestDateAndTime(VirtInstallMachineCase): def setUp(self): super().setUp() def testDefaultState(self): """ Description: Test default state picked up from backend Expected 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.browser m = self.machine i = 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.browser m = self.machine i = 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.browser m = self.machine i = 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.browser m = self.machine i = 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()