Files
hanzo.ai/e2e/unit/limits.spec.ts
zeekay 6c65e3e941 @hanzo/app 0.2.0: the app SDK, renamed from @hanzo/rooms
Every import, the catalog pin and the docs name @hanzo/app and
github.com/hanzoai/app. lib/rooms.ts is lib/app.ts and
components/rooms.tsx is components/app.tsx.
2026-10-22 19:07:20 -07:00

70 lines
3.5 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { readLimits, spendShown } from '@hanzo/app/lib/limits'
import { limitsOf, noticeOf, nearOf } from '@hanzo/ui/product/limits'
/**
* A PLAN'S USAGE IS SHARES, READ IN THE ACTING ORGANIZATION.
*
* GET /v1/ai/limits answers a share per class of model with its state and
* reset, never a count or an amount. The read carries the bearer and the org
* this browser works in; @hanzo/ui checks the body and words a pause.
*/
const LIMITED = {
plan: 'max-20x',
period_start: '2026-09-30T00:00:00Z',
period_end: '2026-10-30T00:00:00Z',
state: 'limited',
classes: {
premium: { percent: 100, state: 'limited', paying: 'none', resets_at: '2026-10-30T00:00:00Z' },
ours: { percent: 85, state: 'near', paying: 'plan', resets_at: '2026-10-30T00:00:00Z' },
},
limited: { reason: 'plan_allowance_used', classes: ['premium'], message: "You've used this period's included premium usage." },
actions: [{ kind: 'upgrade', label: 'Upgrade', url: 'https://hanzo.ai/pricing' }],
}
test('the read carries the bearer and the organization, to the platform', async () => {
const global = globalThis as { window?: unknown; fetch: typeof fetch }
const was = { window: global.window, fetch: global.fetch, had: 'window' in global }
const token = `header.${Buffer.from(JSON.stringify({ orgs: [{ org: 'acme' }] })).toString('base64url')}.signature`
const store = new Map([['hanzo_iam_access_token', token]])
global.window = {
location: { hostname: 'hanzo.ai', origin: 'https://hanzo.ai' },
localStorage: { getItem: (k: string) => store.get(k) ?? null },
}
const heard: { url: string; auth: string | null; org: string | null }[] = []
global.fetch = (async (input: string | URL, init?: RequestInit) => {
const h = new Headers(init?.headers)
heard.push({ url: String(input), auth: h.get('Authorization'), org: h.get('X-Org-Id') })
return new Response(JSON.stringify(LIMITED), { status: 200 })
}) as typeof fetch
try {
expect(await readLimits(new AbortController().signal)).toEqual(LIMITED)
expect(heard).toEqual([{ url: 'https://api.hanzo.ai/v1/ai/limits', auth: `Bearer ${token}`, org: 'acme' }])
global.fetch = (async () => new Response('{}', { status: 404 })) as typeof fetch
await expect(readLimits(new AbortController().signal)).rejects.toMatchObject({ status: 404 })
} finally {
global.fetch = was.fetch
if (was.had) global.window = was.window
else delete global.window
}
})
test('a used-up class is paused until its reset, and no figure is said', () => {
const now = Date.parse('2026-10-03T12:00:00Z')
const limits = limitsOf(LIMITED)
const notice = noticeOf(limits, { served: null, refusal: null }, undefined, now)
expect(notice?.message).toBe('Premium models are paused until Oct 30.')
expect(nearOf(limitsOf({ ...LIMITED, state: 'near', limited: undefined, classes: { premium: { ...LIMITED.classes.premium, percent: 85, state: 'near', paying: 'plan' } } }), now)).toBe(
"You're close to your plan's included premium model usage. Resets Oct 30.",
)
expect(notice?.message).not.toMatch(/\$\s?\d|\d+\s*(requests?|messages?|tokens?)/i)
})
test('a plan holder sees shares, a reader with no plan their spend', () => {
expect(spendShown({ limits: limitsOf(LIMITED), answered: true })).toBe(false)
expect(spendShown({ limits: limitsOf({ plan: '' }), answered: true })).toBe(true)
expect(spendShown({ limits: limitsOf({ plan: 'free' }), answered: true })).toBe(true)
expect(spendShown({ limits: null, answered: false })).toBe(false)
})