11import {
2+ MAX_ABSOLUTE_SCHEDULE_WINDOW_SECONDS ,
23 MAX_SCHEDULE_PHASE ,
34 MINIMUM_SCHEDULE_RANGE_MS ,
45 SCHEDULE_PHASE_DENOMINATOR ,
@@ -7,17 +8,15 @@ import {
78 parseScheduleWindow ,
89 resolveScheduleWindowMs ,
910 validateScheduleWindow ,
10- validateScheduleWindowForInterval ,
1111} from "./scheduleTiming.js" ;
1212
1313describe ( "parseScheduleWindow" , ( ) => {
1414 it . each ( [
1515 [ "30m" , { type : "duration" , durationSeconds : 1_800 } ] ,
1616 [ "2h" , { type : "duration" , durationSeconds : 7_200 } ] ,
17- [ "1d " , { type : "duration" , durationSeconds : 86_400 } ] ,
17+ [ "24h " , { type : "duration" , durationSeconds : 86_400 } ] ,
1818 [ "0m" , { type : "duration" , durationSeconds : 0 } ] ,
1919 [ "0h" , { type : "duration" , durationSeconds : 0 } ] ,
20- [ "0d" , { type : "duration" , durationSeconds : 0 } ] ,
2120 [ "0%" , { type : "percentage" , percentage : 0 } ] ,
2221 [ "12%" , { type : "percentage" , percentage : 12 } ] ,
2322 [ "100%" , { type : "percentage" , percentage : 100 } ] ,
@@ -30,6 +29,10 @@ describe("parseScheduleWindow", () => {
3029 "00m" ,
3130 "01m" ,
3231 "1.5h" ,
32+ "0d" ,
33+ "1d" ,
34+ "25h" ,
35+ "1441m" ,
3336 "30s" ,
3437 "0.01%" ,
3538 "1.0%" ,
@@ -44,8 +47,13 @@ describe("parseScheduleWindow", () => {
4447 expect ( ( ) => parseScheduleWindow ( input ) ) . toThrow ( ) ;
4548 } ) ;
4649
47- it ( "rejects durations that cannot be persisted as a Postgres Int" , ( ) => {
48- expect ( ( ) => parseScheduleWindow ( "24856d" ) ) . toThrow ( "duration is too large" ) ;
50+ it ( "rejects normalized durations over 24 hours" , ( ) => {
51+ expect ( ( ) =>
52+ validateScheduleWindow ( {
53+ type : "duration" ,
54+ durationSeconds : MAX_ABSOLUTE_SCHEDULE_WINDOW_SECONDS + 1 ,
55+ } )
56+ ) . toThrow ( "up to 24 hours" ) ;
4957 } ) ;
5058} ) ;
5159
@@ -58,18 +66,6 @@ describe("schedule window validation", () => {
5866 expect ( ( ) => validateScheduleWindow ( { type : "duration" , durationSeconds : 0 } ) ) . not . toThrow ( ) ;
5967 } ) ;
6068
61- it ( "allows an absolute window equal to the nominal interval" , ( ) => {
62- expect ( ( ) =>
63- validateScheduleWindowForInterval ( { type : "duration" , durationSeconds : 300 } , 5 * 60_000 )
64- ) . not . toThrow ( ) ;
65- } ) ;
66-
67- it ( "rejects an absolute window larger than the nominal interval" , ( ) => {
68- expect ( ( ) =>
69- validateScheduleWindowForInterval ( { type : "duration" , durationSeconds : 1_800 } , 5 * 60_000 )
70- ) . toThrow ( "cannot exceed the interval" ) ;
71- } ) ;
72-
7369 it . each ( [
7470 { type : "duration" , durationSeconds : - 1 } ,
7571 { type : "duration" , durationSeconds : 1.5 } ,
@@ -111,7 +107,7 @@ describe("calculateEffectiveScheduleTime", () => {
111107 windowMs : 0 ,
112108 effectiveRangeMs : MINIMUM_SCHEDULE_RANGE_MS ,
113109 offsetMs : 30_000 ,
114- rangeWasClamped : false ,
110+ windowWasCappedToInterval : false ,
115111 } ) ;
116112 } ) ;
117113
@@ -189,7 +185,7 @@ describe("calculateEffectiveScheduleTime", () => {
189185 expect ( timing . effectiveAt ) . toEqual ( new Date ( "2027-01-01T00:30:00.000Z" ) ) ;
190186 } ) ;
191187
192- it ( "defensively clamps an invalid range to the next nominal tick" , ( ) => {
188+ it ( "caps an absolute window at the interval to the next nominal tick" , ( ) => {
193189 const timing = calculateEffectiveScheduleTime ( {
194190 nominalAt,
195191 nextNominalAt : new Date ( "2026-08-10T10:05:00.000Z" ) ,
@@ -199,7 +195,7 @@ describe("calculateEffectiveScheduleTime", () => {
199195
200196 expect ( timing . windowMs ) . toBe ( 1_800_000 ) ;
201197 expect ( timing . effectiveRangeMs ) . toBe ( 300_000 ) ;
202- expect ( timing . rangeWasClamped ) . toBe ( true ) ;
198+ expect ( timing . windowWasCappedToInterval ) . toBe ( true ) ;
203199 expect ( timing . effectiveAt ) . toEqual ( new Date ( "2026-08-10T10:02:30.000Z" ) ) ;
204200 } ) ;
205201
0 commit comments