@@ -31,35 +31,62 @@ vi.mock("fs/promises", () => ({
3131 writeFile : vi . fn ( ) . mockResolvedValue ( undefined ) ,
3232 readFile : vi . fn ( ) . mockResolvedValue ( "{}" ) ,
3333 mkdir : vi . fn ( ) . mockResolvedValue ( undefined ) ,
34+ access : vi . fn ( ) . mockResolvedValue ( undefined ) ,
35+ rename : vi . fn ( ) . mockResolvedValue ( undefined ) ,
36+ unlink : vi . fn ( ) . mockResolvedValue ( undefined ) ,
3437} ) )
3538
3639// Mock fs (synchronous) for disk cache fallback
3740vi . mock ( "fs" , ( ) => ( {
3841 existsSync : vi . fn ( ) . mockReturnValue ( false ) ,
3942 readFileSync : vi . fn ( ) . mockReturnValue ( "{}" ) ,
43+ createWriteStream : vi . fn ( ) ,
44+ } ) )
45+
46+ // Mock safeWriteJson to avoid stream complexity
47+ vi . mock ( "../../../../utils/safeWriteJson" , ( ) => ( {
48+ safeWriteJson : vi . fn ( ) . mockResolvedValue ( undefined ) ,
49+ } ) )
50+
51+ // Mock proper-lockfile for safeWriteJson
52+ vi . mock ( "proper-lockfile" , ( ) => ( {
53+ lock : vi . fn ( ) . mockResolvedValue ( vi . fn ( ) ) ,
54+ } ) )
55+
56+ // Mock json-stream-stringify to avoid stream complexity
57+ vi . mock ( "json-stream-stringify" , ( ) => ( {
58+ JsonStreamStringify : vi . fn ( ( ) => ( {
59+ on : vi . fn ( ) ,
60+ pipe : vi . fn ( ) ,
61+ } ) ) ,
4062} ) )
4163
4264// Mock all the model fetchers
4365vi . mock ( "../litellm" )
4466vi . mock ( "../openrouter" )
4567vi . mock ( "../requesty" )
4668
47- // Mock ContextProxy with a simple static instance
48- vi . mock ( "../../../core/config/ContextProxy" , ( ) => ( {
49- ContextProxy : {
50- instance : {
51- globalStorageUri : {
52- fsPath : "/mock/storage/path" ,
53- } ,
69+ // Mock ContextProxy with a getter to match the static get instance pattern
70+ // Note: Path is ../../../../ because test file is in __tests/ subdirectory
71+ vi . mock ( "../../../../core/config/ContextProxy" , ( ) => {
72+ const mockInstance = {
73+ globalStorageUri : {
74+ fsPath : "/mock/storage/path" ,
5475 } ,
55- } ,
56- } ) )
76+ }
77+ return {
78+ ContextProxy : Object . defineProperty ( { } , "instance" , {
79+ get : ( ) => mockInstance ,
80+ configurable : true ,
81+ } ) ,
82+ }
83+ } )
5784
5885// Then imports
5986import type { Mock } from "vitest"
6087import * as fsSync from "fs"
6188import NodeCache from "node-cache"
62- import { getModels , getModelsFromCache } from "../modelCache"
89+ import { getModels , getModelsFromCache , isAuthScopedProvider , writeModels } from "../modelCache"
6390import { getLiteLLMModels } from "../litellm"
6491import { getOpenRouterModels } from "../openrouter"
6592import { getRequestyModels } from "../requesty"
@@ -198,10 +225,6 @@ describe("getModelsFromCache disk fallback", () => {
198225 } )
199226
200227 it ( "returns disk cache data when memory cache misses and context is available" , ( ) => {
201- // Note: This test validates the logic but the ContextProxy mock in test environment
202- // returns undefined for getCacheDirectoryPathSync, which is expected behavior
203- // when the context is not fully initialized. The actual disk cache loading
204- // is validated through integration tests.
205228 const diskModels = {
206229 "disk-model" : {
207230 maxTokens : 4096 ,
@@ -215,9 +238,8 @@ describe("getModelsFromCache disk fallback", () => {
215238
216239 const result = getModelsFromCache ( "openrouter" )
217240
218- // In the test environment, ContextProxy.instance may not be fully initialized,
219- // so getCacheDirectoryPathSync returns undefined and disk cache is not attempted
220- expect ( result ) . toBeUndefined ( )
241+ // With the ContextProxy mock properly configured, disk cache is now accessible
242+ expect ( result ) . toEqual ( diskModels )
221243 } )
222244
223245 it ( "handles disk read errors gracefully" , ( ) => {
@@ -434,3 +456,31 @@ describe("empty cache protection", () => {
434456 } )
435457 } )
436458} )
459+
460+ describe ( "isAuthScopedProvider" , ( ) => {
461+ it ( "should return true for zoo-gateway provider" , ( ) => {
462+ expect ( isAuthScopedProvider ( "zoo-gateway" ) ) . toBe ( true )
463+ } )
464+
465+ it ( "should return false for non-auth-scoped providers" , ( ) => {
466+ expect ( isAuthScopedProvider ( "openrouter" ) ) . toBe ( false )
467+ expect ( isAuthScopedProvider ( "litellm" ) ) . toBe ( false )
468+ expect ( isAuthScopedProvider ( "requesty" ) ) . toBe ( false )
469+ expect ( isAuthScopedProvider ( "ollama" ) ) . toBe ( false )
470+ expect ( isAuthScopedProvider ( "lmstudio" ) ) . toBe ( false )
471+ } )
472+ } )
473+
474+ describe ( "writeModels" , ( ) => {
475+ it ( "should write models to cache directory" , async ( ) => {
476+ const mockModels = {
477+ "test-model" : {
478+ maxTokens : 4096 ,
479+ contextWindow : 128000 ,
480+ supportsPromptCache : false ,
481+ } ,
482+ }
483+
484+ await expect ( writeModels ( "openrouter" , mockModels ) ) . resolves . toBeUndefined ( )
485+ } )
486+ } )
0 commit comments