mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +00:00
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.
65 lines
3.5 KiB
TypeScript
65 lines
3.5 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import { billed, planRequired } from '@hanzo/app/failure'
|
|
|
|
/**
|
|
* A REFUSAL ASKS FOR A PLAN BY ITS CODE.
|
|
*
|
|
* The gateway refuses a model the plan does not include with 402 and
|
|
* `{"error":{"code":"plan_required","upgrade_url":…}}`. The code decides, never
|
|
* the sentence, and the address it names is followed only when it is an https
|
|
* page on hanzo.ai or one of its hosts.
|
|
*/
|
|
|
|
const refused = (status: number, error: unknown) => ({ status, body: { error } })
|
|
|
|
test('402 plan_required asks, with the address it names', () => {
|
|
const href = 'https://pay.hanzo.ai/?plan=dev'
|
|
expect(planRequired(refused(402, { code: 'plan_required', upgrade_url: href }))).toEqual({ href })
|
|
expect(planRequired(refused(402, { code: 'plan_required' }))).toEqual({ href: undefined })
|
|
})
|
|
|
|
test('the Free plan\'s limits ask, each by its own status', () => {
|
|
const href = 'https://hanzo.ai/pay'
|
|
expect(planRequired(refused(402, { code: 'allowance_spent', upgrade_url: href }))).toEqual({ href })
|
|
expect(planRequired(refused(429, { code: 'pool_exhausted', upgrade_url: href }))).toEqual({ href })
|
|
expect(planRequired(refused(429, { code: 'pool_busy', upgrade_url: href }))).toEqual({ href })
|
|
// A spent Free day is 429 allowance_spent since the gateway's free notice (hanzoai/ai object/free_notice.go; @hanzo/app
|
|
// a2f7fc0): it asks for the plan, with no address when the gateway names none. The pool's codes are 429 alone.
|
|
expect(planRequired(refused(429, { code: 'allowance_spent' }))).toEqual({ href: undefined })
|
|
expect(planRequired(refused(402, { code: 'pool_exhausted' }))).toBeNull()
|
|
})
|
|
|
|
test('any other refusal does not ask, whatever its sentence says', () => {
|
|
expect(planRequired(refused(402, { code: 'insufficient_balance', message: 'plan_required' }))).toBeNull()
|
|
expect(planRequired(refused(403, { code: 'plan_required' }))).toBeNull()
|
|
expect(planRequired(new Error('plan_required'))).toBeNull()
|
|
expect(planRequired(null)).toBeNull()
|
|
})
|
|
|
|
test('an address off hanzo.ai, or not https, is not followed', () => {
|
|
for (const href of ['javascript:alert(1)', 'http://pay.hanzo.ai/', 'https://pay.hanzo.ai.example.com/', 'https://evil.test/?h=hanzo.ai', 'not a url']) {
|
|
expect(planRequired(refused(402, { code: 'plan_required', upgrade_url: href }))).toEqual({ href: undefined })
|
|
}
|
|
expect(planRequired(refused(402, { code: 'plan_required', upgrade_url: 'https://hanzo.ai/pricing' }))).toEqual({
|
|
href: 'https://hanzo.ai/pricing',
|
|
})
|
|
})
|
|
|
|
/**
|
|
* A BILLING REFUSAL IS READ FROM ITS ENVELOPE.
|
|
*
|
|
* 402 plan_allowance_used / paid_plan_required / insufficient_balance and 429
|
|
* free_plan_cap carry `{"error":{"type":"billing_error",…}}`; any other
|
|
* refusal is not one.
|
|
*/
|
|
test('a billing refusal is read from its envelope, and nothing else is', () => {
|
|
const at = '2026-10-30T00:00:00Z'
|
|
const bill = (status: number, error: Record<string, unknown>) => billed(refused(status, { type: 'billing_error', ...error }))
|
|
expect(bill(402, { code: 'plan_allowance_used', message: 'm', class: 'premium', resets_at: at })).toMatchObject({ status: 402, code: 'plan_allowance_used', class: 'premium', resets_at: at })
|
|
expect(bill(429, { code: 'free_plan_cap', message: 'm' })).toMatchObject({ status: 429, code: 'free_plan_cap' })
|
|
expect(billed(refused(429, { code: 'pool_busy', type: 'rate_limit_error' }))).toBeNull()
|
|
expect(billed(refused(500, { code: 'plan_allowance_used', type: 'billing_error' }))).toBeNull()
|
|
expect(billed(new Error('billing_error'))).toBeNull()
|
|
expect(billed(null)).toBeNull()
|
|
})
|