import CodexBarCoreimport Foundationimport Testing struct CopilotUsageModelsTests { @Test func `decodes quota snapshots payload`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "assigned_date": "2025-01-01", "quota_reset_date": "2025-02-01", "quota_snapshots": { "premium_interactions": { "entitlement": 500, "remaining": 450, "percent_remaining": 90, "quota_id": "premium_interactions" }, "chat": { "entitlement": 300, "remaining": 150, "percent_remaining": 50, "quota_id": "chat" } } } """) #expect(response.copilotPlan == "free") #expect(response.assignedDate == "2025-01-01") #expect(response.quotaResetDate == "2025-02-01") #expect(response.quotaSnapshots.premiumInteractions?.remaining == 450) #expect(response.quotaSnapshots.chat?.remaining == 150) } @Test func `decodes chat only quota snapshots payload`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 200, "remaining": 75, "percent_remaining": 37.5, "quota_id": "chat" } } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat?.quotaId == "chat") #expect(response.quotaSnapshots.chat?.entitlement == 200) #expect(response.quotaSnapshots.chat?.remaining == 75) } @Test func `preserves missing date fields as nil`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 200, "remaining": 75, "percent_remaining": 37.5, "quota_id": "chat" } } } """) #expect(response.assignedDate == nil) #expect(response.quotaResetDate == nil) } @Test func `preserves explicit empty date fields`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "assigned_date": "", "quota_reset_date": "", "quota_snapshots": { "chat": { "entitlement": 200, "remaining": 75, "percent_remaining": 37.5, "quota_id": "chat" } } } """) #expect(response.assignedDate?.isEmpty == true) #expect(response.quotaResetDate?.isEmpty == true) } @Test func `decodes monthly and limited quota payload`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "monthly_quotas": { "chat": "500", "completions": 300 }, "limited_user_quotas": { "chat": 125, "completions": "75" } } """) #expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions") #expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300) #expect(response.quotaSnapshots.premiumInteractions?.remaining == 75) #expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 25) #expect(response.quotaSnapshots.chat?.quotaId == "chat") #expect(response.quotaSnapshots.chat?.entitlement == 500) #expect(response.quotaSnapshots.chat?.remaining == 125) #expect(response.quotaSnapshots.chat?.percentRemaining == 25) } @Test func `does not assume full quota when limited quotas are missing`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "monthly_quotas": { "chat": 500, "completions": 300 } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat == nil) } @Test func `computes monthly fallback per quota only when limited value exists`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "monthly_quotas": { "chat": 500, "completions": 300 }, "limited_user_quotas": { "completions": 60 } } """) #expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions") #expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300) #expect(response.quotaSnapshots.premiumInteractions?.remaining == 60) #expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 20) #expect(response.quotaSnapshots.chat == nil) } @Test func `merges direct and monthly fallback lanes when direct is partial`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 200, "remaining": 75, "percent_remaining": 37.5, "quota_id": "chat" } }, "monthly_quotas": { "chat": 500, "completions": 300 }, "limited_user_quotas": { "chat": 125, "completions": 60 } } """) #expect(response.quotaSnapshots.chat?.quotaId == "chat") #expect(response.quotaSnapshots.chat?.entitlement == 200) #expect(response.quotaSnapshots.chat?.remaining == 75) #expect(response.quotaSnapshots.chat?.percentRemaining == 37.5) #expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions") #expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300) #expect(response.quotaSnapshots.premiumInteractions?.remaining == 60) #expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 20) } @Test func `decodes unknown quota snapshot keys using fallback`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "mystery_bucket": { "entitlement": 100, "remaining": 40, "percent_remaining": 40, "quota_id": "mystery_bucket" } } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat?.quotaId == "mystery_bucket") #expect(response.quotaSnapshots.chat?.entitlement == 100) #expect(response.quotaSnapshots.chat?.remaining == 40) #expect(response.quotaSnapshots.chat?.percentRemaining == 40) } @Test func `ignores placeholder known snapshot when selecting unknown key fallback`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "premium_interactions": {}, "mystery_bucket": { "entitlement": 100, "remaining": 40, "percent_remaining": 40, "quota_id": "mystery_bucket" } } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat?.quotaId == "mystery_bucket") #expect(response.quotaSnapshots.chat?.hasPercentRemaining == true) } @Test func `derives percent remaining when missing but entitlement exists`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 120, "remaining": 30, "quota_id": "chat" } } } """) #expect(response.quotaSnapshots.chat?.hasPercentRemaining == true) #expect(response.quotaSnapshots.chat?.percentRemaining == 25) } @Test func `marks percent remaining as unavailable when underdetermined`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "remaining": 30, "quota_id": "chat" } } } """) #expect(response.quotaSnapshots.chat?.hasPercentRemaining == false) #expect(response.quotaSnapshots.chat?.percentRemaining == 0) } @Test func `marks percent remaining as unavailable when remaining is missing`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 120, "quota_id": "chat" } } } """) #expect(response.quotaSnapshots.chat?.hasPercentRemaining == false) #expect(response.quotaSnapshots.chat?.percentRemaining == 0) } @Test func `falls back to monthly when direct snapshot is missing remaining`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "entitlement": 120, "quota_id": "chat" } }, "monthly_quotas": { "chat": 400 }, "limited_user_quotas": { "chat": 100 } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat?.quotaId == "chat") #expect(response.quotaSnapshots.chat?.entitlement == 400) #expect(response.quotaSnapshots.chat?.remaining == 100) #expect(response.quotaSnapshots.chat?.percentRemaining == 25) #expect(response.quotaSnapshots.chat?.hasPercentRemaining == true) } @Test func `falls back to monthly when direct snapshots lack computable percent`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "quota_snapshots": { "chat": { "remaining": 30, "quota_id": "chat" } }, "monthly_quotas": { "chat": 400 }, "limited_user_quotas": { "chat": 100 } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat?.quotaId == "chat") #expect(response.quotaSnapshots.chat?.entitlement == 400) #expect(response.quotaSnapshots.chat?.remaining == 100) #expect(response.quotaSnapshots.chat?.percentRemaining == 25) #expect(response.quotaSnapshots.chat?.hasPercentRemaining == true) } @Test func `skips monthly fallback when monthly denominator is zero`() throws { let response = try Self.decodeFixture( """ { "copilot_plan": "free", "monthly_quotas": { "chat": 0 }, "limited_user_quotas": { "chat": 0 } } """) #expect(response.quotaSnapshots.premiumInteractions == nil) #expect(response.quotaSnapshots.chat == nil) } private static func decodeFixture(_ fixture: String) throws -> CopilotUsageResponse { try JSONDecoder().decode(CopilotUsageResponse.self, from: Data(fixture.utf8)) }}
import CodexBarCore
import Foundation
import Testing
struct CopilotUsageModelsTests {
@Test
func `decodes quota snapshots payload`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"assigned_date": "2025-01-01",
"quota_reset_date": "2025-02-01",
"quota_snapshots": {
"premium_interactions": {
"entitlement": 500,
"remaining": 450,
"percent_remaining": 90,
"quota_id": "premium_interactions"
},
"chat": {
"entitlement": 300,
"remaining": 150,
"percent_remaining": 50,
"quota_id": "chat"
}
}
}
""")
#expect(response.copilotPlan == "free")
#expect(response.assignedDate == "2025-01-01")
#expect(response.quotaResetDate == "2025-02-01")
#expect(response.quotaSnapshots.premiumInteractions?.remaining == 450)
#expect(response.quotaSnapshots.chat?.remaining == 150)
}
@Test
func `decodes chat only quota snapshots payload`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 200,
"remaining": 75,
"percent_remaining": 37.5,
"quota_id": "chat"
}
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat?.quotaId == "chat")
#expect(response.quotaSnapshots.chat?.entitlement == 200)
#expect(response.quotaSnapshots.chat?.remaining == 75)
}
@Test
func `preserves missing date fields as nil`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 200,
"remaining": 75,
"percent_remaining": 37.5,
"quota_id": "chat"
}
}
}
""")
#expect(response.assignedDate == nil)
#expect(response.quotaResetDate == nil)
}
@Test
func `preserves explicit empty date fields`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"assigned_date": "",
"quota_reset_date": "",
"quota_snapshots": {
"chat": {
"entitlement": 200,
"remaining": 75,
"percent_remaining": 37.5,
"quota_id": "chat"
}
}
}
""")
#expect(response.assignedDate?.isEmpty == true)
#expect(response.quotaResetDate?.isEmpty == true)
}
@Test
func `decodes monthly and limited quota payload`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"monthly_quotas": {
"chat": "500",
"completions": 300
},
"limited_user_quotas": {
"chat": 125,
"completions": "75"
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions")
#expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300)
#expect(response.quotaSnapshots.premiumInteractions?.remaining == 75)
#expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 25)
#expect(response.quotaSnapshots.chat?.quotaId == "chat")
#expect(response.quotaSnapshots.chat?.entitlement == 500)
#expect(response.quotaSnapshots.chat?.remaining == 125)
#expect(response.quotaSnapshots.chat?.percentRemaining == 25)
}
@Test
func `does not assume full quota when limited quotas are missing`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"monthly_quotas": {
"chat": 500,
"completions": 300
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat == nil)
}
@Test
func `computes monthly fallback per quota only when limited value exists`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"monthly_quotas": {
"chat": 500,
"completions": 300
},
"limited_user_quotas": {
"completions": 60
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions")
#expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300)
#expect(response.quotaSnapshots.premiumInteractions?.remaining == 60)
#expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 20)
#expect(response.quotaSnapshots.chat == nil)
}
@Test
func `merges direct and monthly fallback lanes when direct is partial`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 200,
"remaining": 75,
"percent_remaining": 37.5,
"quota_id": "chat"
}
},
"monthly_quotas": {
"chat": 500,
"completions": 300
},
"limited_user_quotas": {
"chat": 125,
"completions": 60
}
}
""")
#expect(response.quotaSnapshots.chat?.quotaId == "chat")
#expect(response.quotaSnapshots.chat?.entitlement == 200)
#expect(response.quotaSnapshots.chat?.remaining == 75)
#expect(response.quotaSnapshots.chat?.percentRemaining == 37.5)
#expect(response.quotaSnapshots.premiumInteractions?.quotaId == "completions")
#expect(response.quotaSnapshots.premiumInteractions?.entitlement == 300)
#expect(response.quotaSnapshots.premiumInteractions?.remaining == 60)
#expect(response.quotaSnapshots.premiumInteractions?.percentRemaining == 20)
}
@Test
func `decodes unknown quota snapshot keys using fallback`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"mystery_bucket": {
"entitlement": 100,
"remaining": 40,
"percent_remaining": 40,
"quota_id": "mystery_bucket"
}
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat?.quotaId == "mystery_bucket")
#expect(response.quotaSnapshots.chat?.entitlement == 100)
#expect(response.quotaSnapshots.chat?.remaining == 40)
#expect(response.quotaSnapshots.chat?.percentRemaining == 40)
}
@Test
func `ignores placeholder known snapshot when selecting unknown key fallback`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"premium_interactions": {},
"mystery_bucket": {
"entitlement": 100,
"remaining": 40,
"percent_remaining": 40,
"quota_id": "mystery_bucket"
}
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat?.quotaId == "mystery_bucket")
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == true)
}
@Test
func `derives percent remaining when missing but entitlement exists`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 120,
"remaining": 30,
"quota_id": "chat"
}
}
}
""")
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == true)
#expect(response.quotaSnapshots.chat?.percentRemaining == 25)
}
@Test
func `marks percent remaining as unavailable when underdetermined`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"remaining": 30,
"quota_id": "chat"
}
}
}
""")
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == false)
#expect(response.quotaSnapshots.chat?.percentRemaining == 0)
}
@Test
func `marks percent remaining as unavailable when remaining is missing`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 120,
"quota_id": "chat"
}
}
}
""")
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == false)
#expect(response.quotaSnapshots.chat?.percentRemaining == 0)
}
@Test
func `falls back to monthly when direct snapshot is missing remaining`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"entitlement": 120,
"quota_id": "chat"
}
},
"monthly_quotas": {
"chat": 400
},
"limited_user_quotas": {
"chat": 100
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat?.quotaId == "chat")
#expect(response.quotaSnapshots.chat?.entitlement == 400)
#expect(response.quotaSnapshots.chat?.remaining == 100)
#expect(response.quotaSnapshots.chat?.percentRemaining == 25)
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == true)
}
@Test
func `falls back to monthly when direct snapshots lack computable percent`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"quota_snapshots": {
"chat": {
"remaining": 30,
"quota_id": "chat"
}
},
"monthly_quotas": {
"chat": 400
},
"limited_user_quotas": {
"chat": 100
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat?.quotaId == "chat")
#expect(response.quotaSnapshots.chat?.entitlement == 400)
#expect(response.quotaSnapshots.chat?.remaining == 100)
#expect(response.quotaSnapshots.chat?.percentRemaining == 25)
#expect(response.quotaSnapshots.chat?.hasPercentRemaining == true)
}
@Test
func `skips monthly fallback when monthly denominator is zero`() throws {
let response = try Self.decodeFixture(
"""
{
"copilot_plan": "free",
"monthly_quotas": {
"chat": 0
},
"limited_user_quotas": {
"chat": 0
}
}
""")
#expect(response.quotaSnapshots.premiumInteractions == nil)
#expect(response.quotaSnapshots.chat == nil)
}
private static func decodeFixture(_ fixture: String) throws -> CopilotUsageResponse {
try JSONDecoder().decode(CopilotUsageResponse.self, from: Data(fixture.utf8))
}
}