import Foundation import Testing @testable import CodexBarCore @Suite struct MiniMaxCookieHeaderTests { @Test func normalizesRawCookieHeader() { let raw = "foo=bar; session=abc123" let normalized = MiniMaxCookieHeader.normalized(from: raw) #expect(normalized == "foo=bar; session=abc123") } @Test func extractsFromCookieHeaderLine() { let raw = "Cookie: foo=bar; session=abc123" let normalized = MiniMaxCookieHeader.normalized(from: raw) #expect(normalized == "foo=bar; session=abc123") } @Test func extractsFromCurlHeader() { let raw = "curl https://platform.minimax.io -H 'Cookie: foo=bar; session=abc123' -H 'accept: */*'" let normalized = MiniMaxCookieHeader.normalized(from: raw) #expect(normalized == "foo=bar; session=abc123") } @Test func extractsFromCurlCookieFlag() { let raw = "curl https://platform.minimax.io --cookie 'foo=bar; session=abc123'" let normalized = MiniMaxCookieHeader.normalized(from: raw) #expect(normalized == "foo=bar; session=abc123") } @Test func extractsAuthAndGroupIDFromCurl() { let raw = """ curl 'https://platform.minimax.io/v1/api/openplatform/coding_plan/remains?GroupId=123456' \ -H 'authorization: Bearer token123' \ -H 'Cookie: foo=bar; session=abc123' """ let override = MiniMaxCookieHeader.override(from: raw) #expect(override?.cookieHeader == "foo=bar; session=abc123") #expect(override?.authorizationToken == "token123") #expect(override?.groupID == "123456") } @Test func extractsAuthFromUppercaseHeader() { let raw = """ curl 'https://platform.minimax.io/v1/api/openplatform/coding_plan/remains?GROUP_ID=98765' \ -H 'Authorization: Bearer token-abc' \ -H 'Cookie: foo=bar; session=abc123' """ let override = MiniMaxCookieHeader.override(from: raw) #expect(override?.authorizationToken == "token-abc") #expect(override?.groupID == "98765") } } @Suite struct MiniMaxUsageParserTests { @Test func parsesCodingPlanSnapshot() throws { let now = Date(timeIntervalSince1970: 1_700_000_000) let html = """
Coding Plan
Max
Available usage: 1,000 prompts / 5 hours
Current Usage
0% Used
Resets in 4 min
""" let snapshot = try MiniMaxUsageParser.parse(html: html, now: now) #expect(snapshot.planName == "Max") #expect(snapshot.availablePrompts == 1000) #expect(snapshot.windowMinutes == 300) #expect(snapshot.usedPercent == 0) #expect(snapshot.resetsAt == now.addingTimeInterval(240)) let usage = snapshot.toUsageSnapshot() #expect(usage.primary?.resetDescription == "1000 prompts / 5 hours") } @Test func parsesCodingPlanRemainsResponse() throws { let now = Date(timeIntervalSince1970: 1_700_000_000) let start = 1_700_000_000_000 let end = start + 5 * 60 * 60 * 1000 let json = """ { "base_resp": { "status_code": 0 }, "current_subscribe_title": "Max", "model_remains": [ { "current_interval_total_count": 1000, "current_interval_usage_count": 250, "start_time": \(start), "end_time": \(end), "remains_time": 240000 } ] } """ let snapshot = try MiniMaxUsageParser.parseCodingPlanRemains(data: Data(json.utf8), now: now) let expectedReset = Date(timeIntervalSince1970: TimeInterval(end) / 1000) #expect(snapshot.planName == "Max") #expect(snapshot.availablePrompts == 1000) #expect(snapshot.windowMinutes == 300) #expect(snapshot.usedPercent == 75) #expect(snapshot.resetsAt == expectedReset) } @Test func parsesCodingPlanRemainsFromDataWrapper() throws { let now = Date(timeIntervalSince1970: 1_700_000_100) let start = 1_700_000_000_000 let end = start + 5 * 60 * 60 * 1000 let json = """ { "base_resp": { "status_code": "0" }, "data": { "current_subscribe_title": "Max", "model_remains": [ { "current_interval_total_count": "15000", "current_interval_usage_count": "14989", "start_time": \(start), "end_time": \(end), "remains_time": 8941292 } ] } } """ let snapshot = try MiniMaxUsageParser.parseCodingPlanRemains(data: Data(json.utf8), now: now) let expectedUsed = Double(11) / Double(15000) * 100 let expectedReset = Date(timeIntervalSince1970: TimeInterval(end) / 1000) #expect(snapshot.planName == "Max") #expect(snapshot.availablePrompts == 15000) #expect(snapshot.windowMinutes == 300) #expect(abs((snapshot.usedPercent ?? 0) - expectedUsed) < 0.01) #expect(snapshot.resetsAt == expectedReset) } @Test func parsesCodingPlanFromNextData() throws { let now = Date(timeIntervalSince1970: 1_700_000_000) let start = 1_700_000_000_000 let end = start + 5 * 60 * 60 * 1000 let json = """ { "props": { "pageProps": { "data": { "base_resp": { "status_code": 0 }, "current_subscribe_title": "Max", "model_remains": [ { "current_interval_total_count": 1000, "current_interval_usage_count": 250, "start_time": \(start), "end_time": \(end), "remains_time": 240000 } ] } } } } """ let html = """ """ let snapshot = try MiniMaxUsageParser.parse(html: html, now: now) let expectedReset = Date(timeIntervalSince1970: TimeInterval(end) / 1000) #expect(snapshot.planName == "Max") #expect(snapshot.availablePrompts == 1000) #expect(snapshot.windowMinutes == 300) #expect(snapshot.usedPercent == 75) #expect(snapshot.resetsAt == expectedReset) } @Test func parsesHTMLWithUsedPrefixAndResetTime() throws { var calendar = Calendar(identifier: .gregorian) calendar.timeZone = TimeZone(identifier: "UTC") ?? .current let now = calendar.date(from: DateComponents(year: 2025, month: 1, day: 1, hour: 10, minute: 0))! let expectedReset = calendar.date(from: DateComponents(year: 2025, month: 1, day: 1, hour: 23, minute: 30))! let html = """
Coding Plan Pro
Available usage: 1,500 prompts / 1.5 hours
Used 75%
Resets at 23:30 (UTC)
""" let snapshot = try MiniMaxUsageParser.parse(html: html, now: now) #expect(snapshot.planName == "Pro") #expect(snapshot.availablePrompts == 1500) #expect(snapshot.windowMinutes == 90) #expect(snapshot.usedPercent == 75) #expect(snapshot.resetsAt == expectedReset) } @Test func throwsOnMissingCookieResponse() { let json = """ { "base_resp": { "status_code": 1004, "status_msg": "cookie is missing, log in again" } } """ #expect(throws: MiniMaxUsageError.invalidCredentials) { try MiniMaxUsageParser.parseCodingPlanRemains(data: Data(json.utf8)) } } @Test func throwsOnStringStatusCodeWhenLoggedOut() { let json = """ { "base_resp": { "status_code": "1004", "status_msg": "login required" } } """ #expect(throws: MiniMaxUsageError.invalidCredentials) { try MiniMaxUsageParser.parseCodingPlanRemains(data: Data(json.utf8)) } } }