@@ -1693,6 +1693,90 @@ describe("AccountsPage", () => {
16931693 ) . toHaveClass ( "is-danger" ) ;
16941694 } ) ;
16951695
1696+ it ( "renders fallback usage windows for lua-driven third-party accounts" , async ( ) => {
1697+ const accountList = [
1698+ {
1699+ id : 35 ,
1700+ provider_type : "openai-compatible" ,
1701+ account_name : "lua-main" ,
1702+ source_icon : "openai" ,
1703+ auth_mode : "api_key" ,
1704+ base_url : "https://w.ciykj.cn" ,
1705+ status : "active" ,
1706+ is_active : false ,
1707+ priority : 1 ,
1708+ account_driver : "builtin_api_key" ,
1709+ usage_driver : "lua" ,
1710+ usage_config_json : '{"script":"managed:w.ciykj.cn"}' ,
1711+ balance : 0 ,
1712+ quota_remaining : 0 ,
1713+ rpm_remaining : 0 ,
1714+ tpm_remaining : 0 ,
1715+ health_score : 1 ,
1716+ recent_error_rate : 0 ,
1717+ last_total_tokens : 0 ,
1718+ last_input_tokens : 0 ,
1719+ last_output_tokens : 0 ,
1720+ model_context_window : 0 ,
1721+ primary_used_percent : 0 ,
1722+ secondary_used_percent : 0 ,
1723+ } ,
1724+ ] ;
1725+
1726+ const fetchMock = vi . fn ( ( input : RequestInfo | URL , init ?: RequestInit ) => {
1727+ const url = String ( input ) ;
1728+ if (
1729+ url === "/ai-router/api/accounts" &&
1730+ ( ! init ?. method || init . method === "GET" )
1731+ ) {
1732+ return Promise . resolve (
1733+ new Response ( JSON . stringify ( accountList ) , {
1734+ status : 200 ,
1735+ headers : { "Content-Type" : "application/json" } ,
1736+ } ) ,
1737+ ) ;
1738+ }
1739+ if (
1740+ url === "/ai-router/api/accounts/usage" &&
1741+ ( ! init ?. method || init . method === "GET" )
1742+ ) {
1743+ return Promise . resolve (
1744+ new Response (
1745+ JSON . stringify ( [
1746+ {
1747+ account_id : 35 ,
1748+ balance : 0 ,
1749+ quota_remaining : 29994 ,
1750+ rpm_remaining : 0 ,
1751+ tpm_remaining : 0 ,
1752+ health_score : 1 ,
1753+ recent_error_rate : 0 ,
1754+ last_total_tokens : 0 ,
1755+ last_input_tokens : 0 ,
1756+ last_output_tokens : 0 ,
1757+ model_context_window : 0 ,
1758+ primary_used_percent : 23 ,
1759+ secondary_used_percent : 67 ,
1760+ } ,
1761+ ] ) ,
1762+ { status : 200 , headers : { "Content-Type" : "application/json" } } ,
1763+ ) ,
1764+ ) ;
1765+ }
1766+ return Promise . resolve ( new Response ( null , { status : 404 } ) ) ;
1767+ } ) ;
1768+
1769+ vi . stubGlobal ( "fetch" , fetchMock ) ;
1770+
1771+ renderAccountsPage ( ) ;
1772+
1773+ expect ( await screen . findByText ( "lua-main" ) ) . toBeInTheDocument ( ) ;
1774+ expect ( await screen . findByText ( "P1" ) ) . toBeInTheDocument ( ) ;
1775+ expect ( screen . getByText ( "P2" ) ) . toBeInTheDocument ( ) ;
1776+ expect ( screen . getByText ( "77%" ) ) . toBeInTheDocument ( ) ;
1777+ expect ( screen . getByText ( "33%" ) ) . toBeInTheDocument ( ) ;
1778+ } ) ;
1779+
16961780 it ( "keeps previous usage visible while a refresh is pending" , async ( ) => {
16971781 const accountList = [
16981782 {
0 commit comments