@@ -10,16 +10,21 @@ const satisfiesGatewayMinimumMock = vi.fn();
1010const resolveRuntimeServiceVersionMock = vi . fn ( ) ;
1111const installPluginFromArchiveMock = vi . fn ( ) ;
1212
13- vi . mock ( "../infra/clawhub.js" , ( ) => ( {
14- parseClawHubPluginSpec : ( ...args : unknown [ ] ) => parseClawHubPluginSpecMock ( ...args ) ,
15- fetchClawHubPackageDetail : ( ...args : unknown [ ] ) => fetchClawHubPackageDetailMock ( ...args ) ,
16- fetchClawHubPackageVersion : ( ...args : unknown [ ] ) => fetchClawHubPackageVersionMock ( ...args ) ,
17- downloadClawHubPackageArchive : ( ...args : unknown [ ] ) => downloadClawHubPackageArchiveMock ( ...args ) ,
18- resolveLatestVersionFromPackage : ( ...args : unknown [ ] ) =>
19- resolveLatestVersionFromPackageMock ( ...args ) ,
20- satisfiesPluginApiRange : ( ...args : unknown [ ] ) => satisfiesPluginApiRangeMock ( ...args ) ,
21- satisfiesGatewayMinimum : ( ...args : unknown [ ] ) => satisfiesGatewayMinimumMock ( ...args ) ,
22- } ) ) ;
13+ vi . mock ( "../infra/clawhub.js" , async ( ) => {
14+ const actual = await vi . importActual < typeof import ( "../infra/clawhub.js" ) > ( "../infra/clawhub.js" ) ;
15+ return {
16+ ...actual ,
17+ parseClawHubPluginSpec : ( ...args : unknown [ ] ) => parseClawHubPluginSpecMock ( ...args ) ,
18+ fetchClawHubPackageDetail : ( ...args : unknown [ ] ) => fetchClawHubPackageDetailMock ( ...args ) ,
19+ fetchClawHubPackageVersion : ( ...args : unknown [ ] ) => fetchClawHubPackageVersionMock ( ...args ) ,
20+ downloadClawHubPackageArchive : ( ...args : unknown [ ] ) =>
21+ downloadClawHubPackageArchiveMock ( ...args ) ,
22+ resolveLatestVersionFromPackage : ( ...args : unknown [ ] ) =>
23+ resolveLatestVersionFromPackageMock ( ...args ) ,
24+ satisfiesPluginApiRange : ( ...args : unknown [ ] ) => satisfiesPluginApiRangeMock ( ...args ) ,
25+ satisfiesGatewayMinimum : ( ...args : unknown [ ] ) => satisfiesGatewayMinimumMock ( ...args ) ,
26+ } ;
27+ } ) ;
2328
2429vi . mock ( "../version.js" , ( ) => ( {
2530 resolveRuntimeServiceVersion : ( ...args : unknown [ ] ) => resolveRuntimeServiceVersionMock ( ...args ) ,
@@ -29,7 +34,9 @@ vi.mock("./install.js", () => ({
2934 installPluginFromArchive : ( ...args : unknown [ ] ) => installPluginFromArchiveMock ( ...args ) ,
3035} ) ) ;
3136
32- const { formatClawHubSpecifier, installPluginFromClawHub } = await import ( "./clawhub.js" ) ;
37+ const { ClawHubRequestError } = await import ( "../infra/clawhub.js" ) ;
38+ const { CLAWHUB_INSTALL_ERROR_CODE , formatClawHubSpecifier, installPluginFromClawHub } =
39+ await import ( "./clawhub.js" ) ;
3340
3441describe ( "installPluginFromClawHub" , ( ) => {
3542 beforeEach ( ( ) => {
@@ -147,8 +154,43 @@ describe("installPluginFromClawHub", () => {
147154 } ,
148155 } ) ;
149156
150- await expect ( installPluginFromClawHub ( { spec : "clawhub:calendar" } ) ) . rejects . toThrow (
151- 'Use "openclaw skills install calendar" instead.' ,
157+ await expect ( installPluginFromClawHub ( { spec : "clawhub:calendar" } ) ) . resolves . toMatchObject ( {
158+ ok : false ,
159+ code : CLAWHUB_INSTALL_ERROR_CODE . SKILL_PACKAGE ,
160+ error : '"calendar" is a skill. Use "openclaw skills install calendar" instead.' ,
161+ } ) ;
162+ } ) ;
163+
164+ it ( "returns typed package-not-found failures" , async ( ) => {
165+ fetchClawHubPackageDetailMock . mockRejectedValueOnce (
166+ new ClawHubRequestError ( {
167+ path : "/api/v1/packages/demo" ,
168+ status : 404 ,
169+ body : "Package not found" ,
170+ } ) ,
171+ ) ;
172+
173+ await expect ( installPluginFromClawHub ( { spec : "clawhub:demo" } ) ) . resolves . toMatchObject ( {
174+ ok : false ,
175+ code : CLAWHUB_INSTALL_ERROR_CODE . PACKAGE_NOT_FOUND ,
176+ error : "Package not found on ClawHub." ,
177+ } ) ;
178+ } ) ;
179+
180+ it ( "returns typed version-not-found failures" , async ( ) => {
181+ parseClawHubPluginSpecMock . mockReturnValueOnce ( { name : "demo" , version : "9.9.9" } ) ;
182+ fetchClawHubPackageVersionMock . mockRejectedValueOnce (
183+ new ClawHubRequestError ( {
184+ path : "/api/v1/packages/demo/versions/9.9.9" ,
185+ status : 404 ,
186+ body : "Version not found" ,
187+ } ) ,
152188 ) ;
189+
190+ await expect ( installPluginFromClawHub ( { spec :
"clawhub:[email protected] " } ) ) . resolves . toMatchObject ( { 191+ ok : false ,
192+ code : CLAWHUB_INSTALL_ERROR_CODE . VERSION_NOT_FOUND ,
193+ error :
"Version not found on ClawHub: [email protected] ." , 194+ } ) ;
153195 } ) ;
154196} ) ;
0 commit comments