| 1 | import { describe, expect, it, vi } from "vite-plus/test"; |
| 2 | |
| 3 | vi.mock("@expo/ui/jetpack-compose", () => ({ |
| 4 | Button: "Button", |
| 5 | Column: "Column", |
| 6 | LinearProgressIndicator: "LinearProgressIndicator", |
| 7 | Text: "Text", |
| 8 | getMaterialColors: ({ scheme }: { scheme: string }) => ({ |
| 9 | surface: `${scheme}-surface`, |
| 10 | onSurface: `${scheme}-onSurface`, |
| 11 | onSurfaceVariant: `${scheme}-onSurfaceVariant`, |
| 12 | surfaceVariant: `${scheme}-surfaceVariant`, |
| 13 | primary: `${scheme}-primary`, |
| 14 | error: `${scheme}-error`, |
| 15 | }), |
| 16 | })); |
| 17 | |
| 18 | vi.mock("@expo/ui/jetpack-compose/modifiers", () => ({ |
| 19 | fillMaxSize: () => "fillMaxSize", |
| 20 | fillMaxWidth: () => "fillMaxWidth", |
| 21 | height: (value: number) => ({ height: value }), |
| 22 | padding: (...values: number[]) => ({ padding: values }), |
| 23 | paddingAll: (value: number) => ({ paddingAll: value }), |
| 24 | })); |
| 25 | |
| 26 | vi.mock("expo-widgets", () => ({ |
| 27 | createWidget: vi.fn((name: string, layout: unknown) => ({ layout, name })), |
| 28 | })); |
| 29 | |
| 30 | import { SubscriptionUsage } from "./SubscriptionUsage.android"; |
| 31 | import type { SubscriptionUsageSnapshot } from "./subscriptionUsageSnapshot"; |
| 32 | |
| 33 | const now = Date.parse("2026-09-05T12:00:00.000Z"); |
| 34 | const provider = { |
| 35 | name: "Codex", |
| 36 | detail: "Subscription remaining", |
| 37 | windows: [ |
| 38 | { kind: "session", label: "5 hours", remaining: 60, reset: "Next reset Sep 5, 5:00 PM" }, |
| 39 | { kind: "weekly", label: "Weekly", remaining: 8, reset: "Next reset Sep 9, 9:00 AM" }, |
| 40 | ], |
| 41 | expiresAt: now + 60_000, |
| 42 | totalWindows: 2, |
| 43 | } satisfies SubscriptionUsageSnapshot["providers"][number]; |
| 44 | const snapshot = { |
| 45 | checkedAt: now, |
| 46 | url: "t3code-dev://settings/usage?tab=limits", |
| 47 | providers: [provider, { ...provider, name: "Claude" }], |
| 48 | } satisfies SubscriptionUsageSnapshot; |
| 49 | |
| 50 | function render(props: SubscriptionUsageSnapshot, colorScheme: "light" | "dark" = "dark") { |
| 51 | vi.setSystemTime(now); |
| 52 | return JSON.stringify(SubscriptionUsage(props, { colorScheme, configuration: undefined })); |
| 53 | } |
| 54 | |
| 55 | describe("SubscriptionUsage Android layout", () => { |
| 56 | it("renders each window with its remaining share, bar, and reset", () => { |
| 57 | const tree = render(snapshot); |
| 58 | expect(tree).toContain("5 hours · 60% left"); |
| 59 | expect(tree).toContain('"progress":0.6'); |
| 60 | expect(tree).toContain("Next reset Sep 5, 5:00 PM"); |
| 61 | expect(tree).toContain('"progress":0.08'); |
| 62 | expect(tree).toContain('"color":"dark-error"'); |
| 63 | expect(tree).toContain("As of "); |
| 64 | }); |
| 65 | |
| 66 | it("drops the bars and asks for a refresh once the snapshot expires", () => { |
| 67 | const tree = render({ |
| 68 | ...snapshot, |
| 69 | providers: [{ ...provider, expiresAt: now - 1 }], |
| 70 | }); |
| 71 | expect(tree).toContain("Open T3 to refresh"); |
| 72 | expect(tree).not.toContain("LinearProgressIndicator"); |
| 73 | expect(tree).not.toContain("more in T3"); |
| 74 | }); |
| 75 | |
| 76 | it("counts the quotas that did not fit", () => { |
| 77 | const tree = render({ ...snapshot, providers: [{ ...provider, totalWindows: 5 }] }); |
| 78 | expect(tree).toContain("3 more in T3"); |
| 79 | }); |
| 80 | |
| 81 | it("keeps quotas without an expiry deadline visible", () => { |
| 82 | const tree = render({ ...snapshot, providers: [{ ...provider, expiresAt: 0 }] }); |
| 83 | expect(tree).toContain("5 hours · 60% left"); |
| 84 | expect(tree).not.toContain("Open T3 to refresh"); |
| 85 | }); |
| 86 | |
| 87 | it("invites connecting when nothing has been checked", () => { |
| 88 | const tree = render({ checkedAt: 0, providers: [] }, "light"); |
| 89 | expect(tree).toContain("Tap to connect in T3"); |
| 90 | expect(tree).not.toContain("As of "); |
| 91 | expect(tree).toContain('"containerColor":"light-surface"'); |
| 92 | }); |
| 93 | }); |