@@ -72,6 +72,11 @@ def _test_pending_changes() -> PendingChanges:
7272
7373MOCK_SAML_CONNECTOR_NAME = "saml_connector"
7474
75+ # Time picker preferences in their API shape, i.e. the tagged union rather than the bare
76+ # duration and interval the user profile stores.
77+ _INDIVIDUAL_TIME_RANGE = {"option" : "individual" , "duration" : 14400 }
78+ _INDIVIDUAL_REFRESH_TIME = {"option" : "individual" , "interval" : 60 }
79+
7580_is_managed_edition = version .edition (paths .omd_root ) is version .Edition .ULTIMATEMT
7681
7782
@@ -1479,3 +1484,103 @@ def test_openapi_time_picker_refresh_intervals_match_the_gui_choices() -> None:
14791484 assert set (get_args (IndividualRefreshTimeModel .__annotations__ ["interval" ])) == set (
14801485 GRAPH_REFRESH_INTERVALS_SECONDS
14811486 )
1487+
1488+
1489+ def test_time_picker_defaults_round_trip_via_put (clients : ClientRegistry ) -> None :
1490+ """The two graph defaults survive an edit, one preference at a time.
1491+
1492+ Create carries concrete defaults; edit is the separate, partial path -
1493+ `UpdateTimePickerModel` writes only the keys it was given, so setting one preference must
1494+ leave the other standing.
1495+ """
1496+ username = "time_picker_put_user"
1497+ clients .User .create (username = username , fullname = "Time Picker User" )
1498+
1499+ after_range = clients .User .edit (
1500+ username = username ,
1501+ interface_options = {"time_picker" : {"default_time_range" : _INDIVIDUAL_TIME_RANGE }},
1502+ ).json ["extensions" ]["interface_options" ]["time_picker" ]
1503+ assert after_range ["default_time_range" ] == _INDIVIDUAL_TIME_RANGE
1504+ assert after_range ["default_refresh_time" ] == {"option" : "default" }
1505+
1506+ after_refresh = clients .User .edit (
1507+ username = username ,
1508+ interface_options = {"time_picker" : {"default_refresh_time" : _INDIVIDUAL_REFRESH_TIME }},
1509+ ).json ["extensions" ]["interface_options" ]["time_picker" ]
1510+ assert after_refresh ["default_refresh_time" ] == _INDIVIDUAL_REFRESH_TIME
1511+ # The first edit is still there, so the second one patched rather than replaced.
1512+ assert after_refresh ["default_time_range" ] == _INDIVIDUAL_TIME_RANGE
1513+
1514+ internal_attributes = _load_internal_attributes (UserId (username ))
1515+ assert internal_attributes ["graph_default_time_range" ] == 14400
1516+ assert internal_attributes ["graph_default_refresh_time" ] == 60
1517+ assert (
1518+ clients .User .get (username = username ).json ["extensions" ]["interface_options" ]["time_picker" ]
1519+ == after_refresh
1520+ )
1521+
1522+
1523+ def test_start_of_week_round_trips (clients : ClientRegistry ) -> None :
1524+ """The start-of-week preference survives a create and reaches storage."""
1525+ username = "start_of_week_user"
1526+ extensions = clients .User .create (
1527+ username = username ,
1528+ fullname = "Time Picker User" ,
1529+ interface_options = {"time_picker" : {"start_of_week" : "sunday" }},
1530+ ).json ["extensions" ]["interface_options" ]["time_picker" ]
1531+
1532+ assert extensions ["start_of_week" ] == "sunday"
1533+ assert _load_internal_attributes (UserId (username ))["start_of_week" ] == "sunday"
1534+ assert (
1535+ clients .User .get (username = username ).json ["extensions" ]["interface_options" ]["time_picker" ][
1536+ "start_of_week"
1537+ ]
1538+ == "sunday"
1539+ )
1540+
1541+
1542+ @pytest .mark .parametrize (
1543+ "start_of_week, expected_status_code" ,
1544+ [
1545+ ("monday" , 200 ),
1546+ ("browser_locale" , 200 ),
1547+ # Not a weekday the schema offers; the picker has no way to render it.
1548+ ("funday" , 400 ),
1549+ # A weekday, but the schema deliberately offers only the three the GUI does.
1550+ ("tuesday" , 400 ),
1551+ ],
1552+ )
1553+ def test_invalid_start_of_week_is_rejected (
1554+ clients : ClientRegistry , start_of_week : str , expected_status_code : int
1555+ ) -> None :
1556+ """An unsupported start-of-week is refused rather than stored."""
1557+ resp = clients .User .create (
1558+ username = _random_string (10 ),
1559+ fullname = "Time Picker User" ,
1560+ interface_options = {"time_picker" : {"start_of_week" : start_of_week }},
1561+ expect_ok = expected_status_code == 200 ,
1562+ )
1563+ resp .assert_status_code (expected_status_code )
1564+
1565+
1566+ def test_default_time_range_round_trips_via_post (clients : ClientRegistry ) -> None :
1567+ """The default-time-range preference survives creation.
1568+
1569+ The create path, as against the edit path above: `CreateTimePickerModel` has concrete defaults
1570+ where `UpdateTimePickerModel` has `None`.
1571+ """
1572+ username = "time_picker_post_user"
1573+ extensions = clients .User .create (
1574+ username = username ,
1575+ fullname = "Time Picker User" ,
1576+ interface_options = {"time_picker" : {"default_time_range" : _INDIVIDUAL_TIME_RANGE }},
1577+ ).json ["extensions" ]["interface_options" ]["time_picker" ]
1578+
1579+ assert extensions ["default_time_range" ] == _INDIVIDUAL_TIME_RANGE
1580+ assert _load_internal_attributes (UserId (username ))["graph_default_time_range" ] == 14400
1581+ assert (
1582+ clients .User .get (username = username ).json ["extensions" ]["interface_options" ]["time_picker" ][
1583+ "default_time_range"
1584+ ]
1585+ == _INDIVIDUAL_TIME_RANGE
1586+ )
0 commit comments