@@ -291,21 +291,117 @@ struct CycleTests {
291291 #expect( cycle? . effectiveDate != nil )
292292 }
293293
294- @Test ( " Cycle yymm format " )
295- func yymmFormat( ) {
296- let cycle = Cycle ( yymm: " 2506 " )
297- #expect( cycle? . yymm == " 2506 " )
294+ @Test ( " Cycle navigation with optional returns " )
295+ func navigation( ) {
296+ let cycle = Cycle ( yymm: " 2501 " )
297+ #expect( cycle != nil )
298+ if let cycle {
299+ #expect( cycle. next? . cycleNumber == 2 )
300+ #expect( cycle. next? . year == 2025 )
301+ #expect( cycle. previous? . cycleNumber == 13 )
302+ #expect( cycle. previous? . year == 2024 )
303+ }
298304 }
299305
300- @Test ( " Cycle navigation " )
301- func navigation( ) {
306+ @Test ( " Cycle effective returns currently effective cycle " )
307+ func effectiveCycle( ) {
308+ let effective = Cycle . effective
309+ #expect( effective. isEffective)
310+ #expect( effective. cycleNumber >= 1 && effective. cycleNumber <= 13 )
311+ }
312+
313+ @Test ( " Cycle cycle(for:) returns correct cycle " )
314+ func cycleForDate( ) {
315+ // Use the reference date (Jan 25, 2024 is cycle 2401)
316+ var calendar = Calendar ( identifier: . gregorian)
317+ calendar. timeZone = . gmt
318+ let refDate = calendar. date (
319+ from: DateComponents ( timeZone: . gmt, year: 2024 , month: 1 , day: 25 )
320+ ) !
321+
322+ let cycle = Cycle . cycle ( for: refDate)
323+ #expect( cycle != nil )
324+ #expect( cycle? . year == 2024 )
325+ #expect( cycle? . cycleNumber == 1 )
326+ }
327+
328+ @Test ( " Cycle dateRange covers full cycle " )
329+ func dateRange( ) {
330+ let cycle = Cycle ( yymm: " 2501 " )
331+ #expect( cycle != nil )
332+ if let cycle {
333+ let dateRange = cycle. dateRange
334+ #expect( dateRange != nil )
335+
336+ // Duration should be 28 days
337+ let expectedDuration : TimeInterval = 28 * 24 * 60 * 60
338+ #expect( dateRange? . duration == expectedDuration)
339+ }
340+ }
341+
342+ @Test ( " Cycle contains returns true for date within cycle " )
343+ func containsDateWithinCycle( ) {
344+ let cycle = Cycle ( yymm: " 2501 " )
345+ #expect( cycle != nil )
346+ if let cycle, let effectiveDate = cycle. effectiveDate {
347+ // A date 14 days into the cycle should be contained
348+ var calendar = Calendar ( identifier: . gregorian)
349+ calendar. timeZone = . gmt
350+ let midCycleDate = calendar. date ( byAdding: . day, value: 14 , to: effectiveDate) !
351+ #expect( cycle. contains ( midCycleDate) )
352+ }
353+ }
354+
355+ @Test ( " Cycle contains returns false for date outside cycle " )
356+ func containsDateOutsideCycle( ) {
357+ let cycle = Cycle ( yymm: " 2501 " )
358+ #expect( cycle != nil )
359+ if let cycle, let effectiveDate = cycle. effectiveDate {
360+ // A date 30 days after the effective date should not be contained
361+ var calendar = Calendar ( identifier: . gregorian)
362+ calendar. timeZone = . gmt
363+ let afterDate = calendar. date ( byAdding: . day, value: 30 , to: effectiveDate) !
364+ #expect( !cycle. contains ( afterDate) )
365+ }
366+ }
367+
368+ @Test ( " Cycle expirationDate returns exact moment " )
369+ func expirationDateExactMoment( ) {
302370 let cycle = Cycle ( yymm: " 2501 " )
303371 #expect( cycle != nil )
304372 if let cycle {
305- #expect( cycle. next. cycleNumber == 2 )
306- #expect( cycle. next. year == 2025 )
373+ let expirationDate = cycle. expirationDate
374+ #expect( expirationDate != nil )
375+
376+ // expirationDate should equal next cycle's effectiveDate
377+ #expect( expirationDate == cycle. next? . effectiveDate)
307378 }
308379 }
380+
381+ @Test ( " Cycle comparison " )
382+ func comparison( ) {
383+ let older = Cycle ( yymm: " 2501 " )
384+ let newer = Cycle ( yymm: " 2502 " )
385+ let same = Cycle ( yymm: " 2501 " )
386+ #expect( older != nil && newer != nil && same != nil )
387+ if let older, let newer, let same {
388+ #expect( older < newer)
389+ #expect( newer > older)
390+ #expect( older == same)
391+ }
392+ }
393+
394+ @Test ( " Cycle isEffective returns true for effective cycle " )
395+ func isEffective( ) {
396+ let effective = Cycle . effective
397+ #expect( effective. isEffective)
398+
399+ // A past cycle should not be effective
400+ let past = Cycle ( yymm: " 2401 " )
401+ #expect( past != nil )
402+ // Past cycle may or may not be effective depending on when test runs
403+ _ = past? . isEffective
404+ }
309405}
310406
311407// MARK: - PathTerminator Tests
0 commit comments