@@ -35,6 +35,39 @@ function model(id: string): GatewayModelChoice {
3535
3636const getConfig = ( ) => ( { } ) as OpenClawConfig ;
3737
38+ function createRefreshingCatalogLoader (
39+ firstCatalog : GatewayModelChoice [ ] ,
40+ secondCatalog : GatewayModelChoice [ ] ,
41+ ) {
42+ return vi
43+ . fn < LoadModelCatalogForTest > ( )
44+ . mockResolvedValueOnce ( firstCatalog )
45+ . mockResolvedValueOnce ( secondCatalog ) ;
46+ }
47+
48+ async function expectCatalog (
49+ loadModelCatalog : LoadModelCatalogForTest ,
50+ catalog : GatewayModelChoice [ ] ,
51+ readOnly = true ,
52+ ) {
53+ await expect (
54+ loadGatewayModelCatalog ( {
55+ getConfig,
56+ loadModelCatalog,
57+ ...( readOnly ? { } : { readOnly : false } ) ,
58+ } ) ,
59+ ) . resolves . toBe ( catalog ) ;
60+ }
61+
62+ async function markStaleAndExpectPreviousCatalog (
63+ loadModelCatalog : LoadModelCatalogForTest ,
64+ catalog : GatewayModelChoice [ ] ,
65+ ) {
66+ markGatewayModelCatalogStaleForReload ( ) ;
67+ await expectCatalog ( loadModelCatalog , catalog ) ;
68+ await vi . waitFor ( ( ) => expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 2 ) ) ;
69+ }
70+
3871describe ( "loadGatewayModelCatalog" , ( ) => {
3972 beforeEach ( async ( ) => {
4073 await resetModelCatalogCacheForTest ( ) ;
@@ -82,46 +115,26 @@ describe("loadGatewayModelCatalog", () => {
82115 it ( "caches an empty read-only catalog until reload marks it stale" , async ( ) => {
83116 const emptyCatalog : GatewayModelChoice [ ] = [ ] ;
84117 const freshCatalog = [ model ( "gpt-5.5" ) ] ;
85- const loadModelCatalog = vi
86- . fn < LoadModelCatalogForTest > ( )
87- . mockResolvedValueOnce ( emptyCatalog )
88- . mockResolvedValueOnce ( freshCatalog ) ;
118+ const loadModelCatalog = createRefreshingCatalogLoader ( emptyCatalog , freshCatalog ) ;
89119
90- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
91- emptyCatalog ,
92- ) ;
93- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
94- emptyCatalog ,
95- ) ;
120+ await expectCatalog ( loadModelCatalog , emptyCatalog ) ;
121+ await expectCatalog ( loadModelCatalog , emptyCatalog ) ;
96122
97123 expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 1 ) ;
98124
99- markGatewayModelCatalogStaleForReload ( ) ;
100- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
101- emptyCatalog ,
102- ) ;
103- await vi . waitFor ( ( ) => expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 2 ) ) ;
125+ await markStaleAndExpectPreviousCatalog ( loadModelCatalog , emptyCatalog ) ;
104126 await vi . waitFor ( async ( ) => {
105- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
106- freshCatalog ,
107- ) ;
127+ await expectCatalog ( loadModelCatalog , freshCatalog ) ;
108128 } ) ;
109129 } ) ;
110130
111131 it ( "does not cache an empty full catalog so the next all-model request retries" , async ( ) => {
112132 const emptyCatalog : GatewayModelChoice [ ] = [ ] ;
113133 const freshCatalog = [ model ( "gpt-5.5" ) ] ;
114- const loadModelCatalog = vi
115- . fn < LoadModelCatalogForTest > ( )
116- . mockResolvedValueOnce ( emptyCatalog )
117- . mockResolvedValueOnce ( freshCatalog ) ;
134+ const loadModelCatalog = createRefreshingCatalogLoader ( emptyCatalog , freshCatalog ) ;
118135
119- await expect (
120- loadGatewayModelCatalog ( { getConfig, loadModelCatalog, readOnly : false } ) ,
121- ) . resolves . toBe ( emptyCatalog ) ;
122- await expect (
123- loadGatewayModelCatalog ( { getConfig, loadModelCatalog, readOnly : false } ) ,
124- ) . resolves . toBe ( freshCatalog ) ;
136+ await expectCatalog ( loadModelCatalog , emptyCatalog , false ) ;
137+ await expectCatalog ( loadModelCatalog , freshCatalog , false ) ;
125138
126139 expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 2 ) ;
127140 } ) ;
@@ -135,21 +148,13 @@ describe("loadGatewayModelCatalog", () => {
135148 . mockResolvedValueOnce ( staleCatalog )
136149 . mockReturnValueOnce ( refresh . promise ) ;
137150
138- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
139- staleCatalog ,
140- ) ;
151+ await expectCatalog ( loadModelCatalog , staleCatalog ) ;
141152
142- markGatewayModelCatalogStaleForReload ( ) ;
143- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
144- staleCatalog ,
145- ) ;
146- await vi . waitFor ( ( ) => expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 2 ) ) ;
153+ await markStaleAndExpectPreviousCatalog ( loadModelCatalog , staleCatalog ) ;
147154
148155 refresh . resolve ( freshCatalog ) ;
149156 await vi . waitFor ( async ( ) => {
150- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
151- freshCatalog ,
152- ) ;
157+ await expectCatalog ( loadModelCatalog , freshCatalog ) ;
153158 } ) ;
154159 } ) ;
155160
@@ -162,25 +167,15 @@ describe("loadGatewayModelCatalog", () => {
162167 . mockRejectedValueOnce ( new Error ( "provider offline" ) )
163168 . mockResolvedValueOnce ( freshCatalog ) ;
164169
165- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
166- staleCatalog ,
167- ) ;
170+ await expectCatalog ( loadModelCatalog , staleCatalog ) ;
168171
169- markGatewayModelCatalogStaleForReload ( ) ;
170- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
171- staleCatalog ,
172- ) ;
173- await vi . waitFor ( ( ) => expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 2 ) ) ;
172+ await markStaleAndExpectPreviousCatalog ( loadModelCatalog , staleCatalog ) ;
174173
175- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
176- staleCatalog ,
177- ) ;
174+ await expectCatalog ( loadModelCatalog , staleCatalog ) ;
178175 await vi . waitFor ( ( ) => expect ( loadModelCatalog ) . toHaveBeenCalledTimes ( 3 ) ) ;
179176
180177 await vi . waitFor ( async ( ) => {
181- await expect ( loadGatewayModelCatalog ( { getConfig, loadModelCatalog } ) ) . resolves . toBe (
182- freshCatalog ,
183- ) ;
178+ await expectCatalog ( loadModelCatalog , freshCatalog ) ;
184179 } ) ;
185180 } ) ;
186181} ) ;
0 commit comments