214 lines
8.8 KiB
Swift
214 lines
8.8 KiB
Swift
import CodexBarCore
|
|
import Foundation
|
|
import Testing
|
|
@testable import CodexBar
|
|
|
|
struct CodexResetBackfillSemanticsTests {
|
|
@Test
|
|
func `merged reset cache preserves semantic lanes across swapped snapshots`() throws {
|
|
let now = Date(timeIntervalSince1970: 1_800_000_000)
|
|
let sessionReset = now.addingTimeInterval(4 * 60 * 60)
|
|
let weeklyReset = now.addingTimeInterval(4 * 24 * 60 * 60)
|
|
let canonicalSessionCache = UsageSnapshot(
|
|
primary: RateWindow(
|
|
usedPercent: 17,
|
|
windowMinutes: 300,
|
|
resetsAt: sessionReset,
|
|
resetDescription: nil),
|
|
secondary: nil,
|
|
updatedAt: now.addingTimeInterval(-20))
|
|
let swappedWeeklyCache = UsageSnapshot(
|
|
primary: RateWindow(
|
|
usedPercent: 63,
|
|
windowMinutes: 10080,
|
|
resetsAt: weeklyReset,
|
|
resetDescription: nil),
|
|
secondary: nil,
|
|
updatedAt: now.addingTimeInterval(-10))
|
|
|
|
let merged = try #require(UsageStore.codexMergedResetBackfillSnapshot(
|
|
[canonicalSessionCache, swappedWeeklyCache],
|
|
now: now))
|
|
|
|
#expect(merged.primary?.usedPercent == 17)
|
|
#expect(merged.primary?.windowMinutes == 300)
|
|
#expect(merged.primary?.resetsAt == sessionReset)
|
|
#expect(merged.secondary?.usedPercent == 63)
|
|
#expect(merged.secondary?.windowMinutes == 10080)
|
|
#expect(merged.secondary?.resetsAt == weeklyReset)
|
|
}
|
|
}
|
|
|
|
extension CodexAccountScopedRefreshTests {
|
|
@Test
|
|
func `stacked email only rows use neither prior baselines nor reset backfills`() async throws {
|
|
let fixture = try self.makeEmailOnlyStackedFixture(
|
|
suite: "CodexResetBackfillSemanticsTests-email-only-stacked")
|
|
defer { fixture.cleanup() }
|
|
|
|
let now = Date()
|
|
let weeklyReset = now.addingTimeInterval(3 * 24 * 60 * 60)
|
|
let targetPrior = self.codexWeeklySnapshot(
|
|
email: fixture.target.email,
|
|
weeklyUsedPercent: 74,
|
|
weeklyReset: weeklyReset,
|
|
updatedAt: now.addingTimeInterval(-60))
|
|
let siblingPrior = self.codexWeeklySnapshot(
|
|
email: fixture.sibling.email,
|
|
weeklyUsedPercent: 28,
|
|
weeklyReset: weeklyReset,
|
|
updatedAt: now.addingTimeInterval(-60))
|
|
let priorRows = [
|
|
CodexAccountUsageSnapshot(
|
|
account: fixture.target,
|
|
snapshot: targetPrior,
|
|
error: nil,
|
|
sourceLabel: "cached-target"),
|
|
CodexAccountUsageSnapshot(
|
|
account: fixture.sibling,
|
|
snapshot: siblingPrior,
|
|
error: nil,
|
|
sourceLabel: "cached-sibling"),
|
|
]
|
|
let snapshotStore = RecordingCodexAccountUsageSnapshotStore(initialSnapshots: priorRows)
|
|
let store = self.makeCodexWeeklyPublicationStore(
|
|
settings: fixture.settings,
|
|
suite: "CodexResetBackfillSemanticsTests-email-only-stacked",
|
|
snapshotStore: snapshotStore)
|
|
#expect(store.codexLimitResetOwnerKey(
|
|
forVisibleAccount: fixture.target,
|
|
visibleAccounts: [fixture.target, fixture.sibling]) == nil)
|
|
|
|
let initialLow = self.codexWeeklySnapshot(
|
|
email: fixture.target.email,
|
|
weeklyUsedPercent: 0.2,
|
|
weeklyReset: weeklyReset,
|
|
updatedAt: now.addingTimeInterval(-40))
|
|
let confirmedLow = self.codexWeeklySnapshot(
|
|
email: fixture.target.email,
|
|
weeklyUsedPercent: 0.4,
|
|
weeklyReset: weeklyReset,
|
|
updatedAt: now.addingTimeInterval(-30))
|
|
let partial = self.codexWeeklySnapshot(
|
|
email: fixture.target.email,
|
|
weeklyUsedPercent: nil,
|
|
weeklyReset: nil,
|
|
updatedAt: now.addingTimeInterval(-20),
|
|
sessionUsedPercent: 31)
|
|
let targetLoader = SequencedCodexSnapshotLoader(steps: [
|
|
.success(initialLow),
|
|
.success(confirmedLow),
|
|
.success(partial),
|
|
])
|
|
let siblingCurrent = self.codexWeeklySnapshot(
|
|
email: fixture.sibling.email,
|
|
weeklyUsedPercent: 29,
|
|
weeklyReset: weeklyReset,
|
|
updatedAt: now.addingTimeInterval(-10))
|
|
let targetHomePath = fixture.targetHome.path
|
|
let siblingHomePath = fixture.siblingHome.path
|
|
self.installContextualCodexProvider(on: store) { context in
|
|
switch context.env["CODEX_HOME"] {
|
|
case targetHomePath:
|
|
try await targetLoader.load()
|
|
case siblingHomePath:
|
|
siblingCurrent
|
|
default:
|
|
throw TestRefreshError(message: "Unexpected CODEX_HOME routing")
|
|
}
|
|
}
|
|
|
|
await store.refreshCodexVisibleAccountsForMenu()
|
|
|
|
let confirmedTarget = try #require(store.codexAccountSnapshots.first {
|
|
$0.account.storedAccountID == fixture.target.storedAccountID
|
|
}?.snapshot)
|
|
#expect(confirmedTarget.updatedAt == confirmedLow.updatedAt)
|
|
#expect(confirmedTarget.secondary?.usedPercent == 0.4)
|
|
|
|
await store.refreshCodexVisibleAccountsForMenu()
|
|
|
|
let partialTarget = try #require(store.codexAccountSnapshots.first {
|
|
$0.account.storedAccountID == fixture.target.storedAccountID
|
|
}?.snapshot)
|
|
#expect(await targetLoader.callCount == 3)
|
|
#expect(partialTarget.updatedAt == partial.updatedAt)
|
|
#expect(partialTarget.primary?.usedPercent == 31)
|
|
#expect(partialTarget.secondary == nil)
|
|
}
|
|
|
|
private func makeEmailOnlyStackedFixture(suite: String) throws -> EmailOnlyStackedFixture {
|
|
let settings = self.makeSettingsStore(suite: suite)
|
|
settings.refreshFrequency = .manual
|
|
settings.codexCookieSource = .off
|
|
settings.multiAccountMenuLayout = .stacked
|
|
|
|
let targetID = try #require(UUID(uuidString: "AAAAAAAA-BBBB-CCCC-DDDD-424242424242"))
|
|
let siblingID = try #require(UUID(uuidString: "AAAAAAAA-BBBB-CCCC-DDDD-434343434343"))
|
|
let targetHome = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codex-email-only-target-\(UUID().uuidString)", isDirectory: true)
|
|
let siblingHome = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("codex-email-only-sibling-\(UUID().uuidString)", isDirectory: true)
|
|
try Self.writeCodexAuthFile(
|
|
homeURL: targetHome,
|
|
email: "email-only-target@example.com",
|
|
plan: "Pro")
|
|
try Self.writeCodexAuthFile(
|
|
homeURL: siblingHome,
|
|
email: "email-only-sibling@example.com",
|
|
plan: "Pro")
|
|
let targetFingerprint = try #require(CodexAuthFingerprint.fingerprint(homePath: targetHome.path))
|
|
let siblingFingerprint = try #require(CodexAuthFingerprint.fingerprint(homePath: siblingHome.path))
|
|
let targetAccount = ManagedCodexAccount(
|
|
id: targetID,
|
|
email: "email-only-target@example.com",
|
|
authFingerprint: targetFingerprint,
|
|
managedHomePath: targetHome.path,
|
|
createdAt: 1,
|
|
updatedAt: 2,
|
|
lastAuthenticatedAt: 2)
|
|
let siblingAccount = ManagedCodexAccount(
|
|
id: siblingID,
|
|
email: "email-only-sibling@example.com",
|
|
authFingerprint: siblingFingerprint,
|
|
managedHomePath: siblingHome.path,
|
|
createdAt: 1,
|
|
updatedAt: 2,
|
|
lastAuthenticatedAt: 2)
|
|
let accountStoreURL = try self.makeManagedAccountStoreURL(accounts: [targetAccount, siblingAccount])
|
|
settings._test_managedCodexAccountStoreURL = accountStoreURL
|
|
settings.codexActiveSource = .managedAccount(id: targetID)
|
|
|
|
let projection = settings.codexVisibleAccountProjection
|
|
let target = try #require(projection.visibleAccounts.first { $0.storedAccountID == targetID })
|
|
let sibling = try #require(projection.visibleAccounts.first { $0.storedAccountID == siblingID })
|
|
#expect(target.workspaceAccountID == nil)
|
|
#expect(sibling.workspaceAccountID == nil)
|
|
|
|
return EmailOnlyStackedFixture(
|
|
settings: settings,
|
|
target: target,
|
|
sibling: sibling,
|
|
targetHome: targetHome,
|
|
siblingHome: siblingHome,
|
|
accountStoreURL: accountStoreURL)
|
|
}
|
|
}
|
|
|
|
private struct EmailOnlyStackedFixture {
|
|
let settings: SettingsStore
|
|
let target: CodexVisibleAccount
|
|
let sibling: CodexVisibleAccount
|
|
let targetHome: URL
|
|
let siblingHome: URL
|
|
let accountStoreURL: URL
|
|
|
|
@MainActor
|
|
func cleanup() {
|
|
self.settings._test_managedCodexAccountStoreURL = nil
|
|
try? FileManager.default.removeItem(at: self.accountStoreURL)
|
|
try? FileManager.default.removeItem(at: self.targetHome)
|
|
try? FileManager.default.removeItem(at: self.siblingHome)
|
|
}
|
|
}
|