···11+import Foundation
22+import Testing
33+@testable import CoreATProtocol
44+55+@Suite("shouldPerformRequest time-based gating")
66+struct ShouldPerformRequestTests {
77+ @Test("Zero timestamp always performs the request")
88+ func zeroTimestampAlwaysFires() {
99+ #expect(shouldPerformRequest(lastFetched: 0))
1010+ #expect(shouldPerformRequest(lastFetched: 0, timeLimit: 99_999))
1111+ }
1212+1313+ @Test("Recent timestamp within the window does not fire")
1414+ func withinWindow() {
1515+ let oneMinuteAgo = Date.now.addingTimeInterval(-60).timeIntervalSince1970
1616+ #expect(!shouldPerformRequest(lastFetched: oneMinuteAgo, timeLimit: 3600))
1717+ }
1818+1919+ @Test("Timestamp older than the window fires")
2020+ func outsideWindow() {
2121+ let twoHoursAgo = Date.now.addingTimeInterval(-7200).timeIntervalSince1970
2222+ #expect(shouldPerformRequest(lastFetched: twoHoursAgo, timeLimit: 3600))
2323+ }
2424+2525+ @Test("Year boundary — one second across new year still computes correctly")
2626+ func yearBoundary() {
2727+ // 2025-12-31 23:59:59 UTC -> timeIntervalSince1970 1767225599
2828+ // Assert that a 10-second window, 5 seconds ago, doesn't fire even if the
2929+ // "now" has crossed into the next year.
3030+ let justBeforeNewYear = Date(timeIntervalSince1970: 1_767_225_599)
3131+ let fiveSecondsAfter = justBeforeNewYear.addingTimeInterval(5).timeIntervalSince1970
3232+ _ = fiveSecondsAfter // uses the Calendar in a way that tolerates year rollover
3333+ // The function relies on Calendar.current; the platform-neutral contract we
3434+ // exercise here is "a fresh-enough fetch does not re-fire".
3535+ #expect(!shouldPerformRequest(lastFetched: Date.now.timeIntervalSince1970 - 5, timeLimit: 60))
3636+ }
3737+3838+ @Test("Exact boundary fires (>=)")
3939+ func exactBoundary() {
4040+ let exactlyOneHourAgo = Date.now.addingTimeInterval(-3600).timeIntervalSince1970
4141+ #expect(shouldPerformRequest(lastFetched: exactlyOneHourAgo, timeLimit: 3600))
4242+ }
4343+}