11import { describe , it , expect , vi , beforeEach } from 'vitest' ;
22import { HonoServerPlugin } from './hono-plugin' ;
3- import { PluginContext } from '@objectstack/core' ;
3+ import { PluginContext , ApiRegistry } from '@objectstack/core' ;
44
55describe ( 'HonoServerPlugin' , ( ) => {
66 let context : any ;
77 let logger : any ;
88 let protocol : any ;
9+ let apiRegistry : any ;
910
1011 beforeEach ( ( ) => {
1112 logger = {
@@ -16,14 +17,38 @@ describe('HonoServerPlugin', () => {
1617 } ;
1718
1819 protocol = {
19- findData : vi . fn ( ) ,
20- createData : vi . fn ( )
20+ getDiscovery : vi . fn ( ) . mockResolvedValue ( { version : 'v1' , apiName : 'ObjectStack' } ) ,
21+ getMetaTypes : vi . fn ( ) . mockResolvedValue ( { types : [ 'object' , 'plugin' ] } ) ,
22+ getMetaItems : vi . fn ( ) . mockResolvedValue ( { type : 'object' , items : [ ] } ) ,
23+ findData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , records : [ ] } ) ,
24+ getData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , id : '1' , record : { } } ) ,
25+ createData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , id : '1' , record : { } } ) ,
26+ updateData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , id : '1' , record : { } } ) ,
27+ deleteData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , id : '1' , success : true } ) ,
28+ batchData : vi . fn ( ) . mockResolvedValue ( { total : 0 , succeeded : 0 , failed : 0 } ) ,
29+ createManyData : vi . fn ( ) . mockResolvedValue ( { object : 'test' , records : [ ] , count : 0 } ) ,
30+ updateManyData : vi . fn ( ) . mockResolvedValue ( { total : 0 , succeeded : 0 , failed : 0 } ) ,
31+ deleteManyData : vi . fn ( ) . mockResolvedValue ( { total : 0 , succeeded : 0 , failed : 0 } ) ,
32+ getMetaItemCached : vi . fn ( ) . mockResolvedValue ( { data : { } , notModified : false } ) ,
33+ getUiView : vi . fn ( ) . mockResolvedValue ( { object : 'test' , type : 'list' } )
34+ } ;
35+
36+ apiRegistry = {
37+ registerApi : vi . fn ( ) ,
38+ getRegistry : vi . fn ( ) . mockReturnValue ( {
39+ version : '1.0.0' ,
40+ conflictResolution : 'error' ,
41+ apis : [ ] ,
42+ totalApis : 0 ,
43+ totalEndpoints : 0
44+ } )
2145 } ;
2246
2347 context = {
2448 logger,
2549 getService : vi . fn ( ( service ) => {
2650 if ( service === 'protocol' ) return protocol ;
51+ if ( service === 'api-registry' ) throw new Error ( 'Not found' ) ;
2752 return null ;
2853 } ) ,
2954 registerService : vi . fn ( ) ,
@@ -47,11 +72,119 @@ describe('HonoServerPlugin', () => {
4772 expect ( context . hook ) . toHaveBeenCalledWith ( 'kernel:ready' , expect . any ( Function ) ) ;
4873 } ) ;
4974
50- it ( 'should register CRUD routes' , async ( ) => {
75+ it ( 'should register CRUD routes in legacy mode when API Registry not available ' , async ( ) => {
5176 const plugin = new HonoServerPlugin ( ) ;
5277 await plugin . init ( context as PluginContext ) ;
5378 await plugin . start ( context as PluginContext ) ;
5479
5580 expect ( context . getService ) . toHaveBeenCalledWith ( 'protocol' ) ;
81+ expect ( context . getService ) . toHaveBeenCalledWith ( 'api-registry' ) ;
82+ expect ( logger . debug ) . toHaveBeenCalledWith ( 'API Registry not found, using legacy route registration' ) ;
83+ } ) ;
84+
85+ it ( 'should use API Registry when available' , async ( ) => {
86+ context . getService = vi . fn ( ( service ) => {
87+ if ( service === 'protocol' ) return protocol ;
88+ if ( service === 'api-registry' ) return apiRegistry ;
89+ return null ;
90+ } ) ;
91+
92+ const plugin = new HonoServerPlugin ( ) ;
93+ await plugin . init ( context as PluginContext ) ;
94+ await plugin . start ( context as PluginContext ) ;
95+
96+ expect ( context . getService ) . toHaveBeenCalledWith ( 'api-registry' ) ;
97+ expect ( apiRegistry . registerApi ) . toHaveBeenCalled ( ) ;
98+ } ) ;
99+
100+ it ( 'should register standard endpoints to API Registry' , async ( ) => {
101+ context . getService = vi . fn ( ( service ) => {
102+ if ( service === 'protocol' ) return protocol ;
103+ if ( service === 'api-registry' ) return apiRegistry ;
104+ return null ;
105+ } ) ;
106+
107+ const plugin = new HonoServerPlugin ( ) ;
108+ await plugin . init ( context as PluginContext ) ;
109+ await plugin . start ( context as PluginContext ) ;
110+
111+ expect ( apiRegistry . registerApi ) . toHaveBeenCalledWith (
112+ expect . objectContaining ( {
113+ id : 'objectstack_core_api' ,
114+ name : 'ObjectStack Core API' ,
115+ type : 'rest' ,
116+ version : 'v1'
117+ } )
118+ ) ;
119+ } ) ;
120+
121+ it ( 'should skip standard endpoint registration when disabled' , async ( ) => {
122+ context . getService = vi . fn ( ( service ) => {
123+ if ( service === 'protocol' ) return protocol ;
124+ if ( service === 'api-registry' ) return apiRegistry ;
125+ return null ;
126+ } ) ;
127+
128+ const plugin = new HonoServerPlugin ( { registerStandardEndpoints : false } ) ;
129+ await plugin . init ( context as PluginContext ) ;
130+ await plugin . start ( context as PluginContext ) ;
131+
132+ expect ( apiRegistry . registerApi ) . not . toHaveBeenCalled ( ) ;
133+ } ) ;
134+
135+ it ( 'should use legacy routes when useApiRegistry is disabled' , async ( ) => {
136+ context . getService = vi . fn ( ( service ) => {
137+ if ( service === 'protocol' ) return protocol ;
138+ if ( service === 'api-registry' ) return apiRegistry ;
139+ return null ;
140+ } ) ;
141+
142+ const plugin = new HonoServerPlugin ( { useApiRegistry : false } ) ;
143+ await plugin . init ( context as PluginContext ) ;
144+ await plugin . start ( context as PluginContext ) ;
145+
146+ expect ( apiRegistry . getRegistry ) . not . toHaveBeenCalled ( ) ;
147+ expect ( logger . debug ) . toHaveBeenCalledWith ( 'Using legacy route registration' ) ;
148+ } ) ;
149+
150+ it ( 'should respect REST server configuration' , async ( ) => {
151+ context . getService = vi . fn ( ( service ) => {
152+ if ( service === 'protocol' ) return protocol ;
153+ if ( service === 'api-registry' ) return apiRegistry ;
154+ return null ;
155+ } ) ;
156+
157+ const plugin = new HonoServerPlugin ( {
158+ restConfig : {
159+ api : {
160+ version : 'v2' ,
161+ basePath : '/custom' ,
162+ enableCrud : true ,
163+ enableMetadata : true ,
164+ enableBatch : true
165+ }
166+ }
167+ } ) ;
168+
169+ await plugin . init ( context as PluginContext ) ;
170+ await plugin . start ( context as PluginContext ) ;
171+
172+ expect ( apiRegistry . registerApi ) . toHaveBeenCalledWith (
173+ expect . objectContaining ( {
174+ version : 'v2'
175+ } )
176+ ) ;
177+ } ) ;
178+
179+ it ( 'should handle protocol service not found gracefully' , async ( ) => {
180+ context . getService = vi . fn ( ( ) => {
181+ throw new Error ( 'Service not found' ) ;
182+ } ) ;
183+
184+ const plugin = new HonoServerPlugin ( ) ;
185+ await plugin . init ( context as PluginContext ) ;
186+ await plugin . start ( context as PluginContext ) ;
187+
188+ expect ( logger . warn ) . toHaveBeenCalledWith ( 'Protocol service not found, skipping protocol routes' ) ;
56189 } ) ;
57190} ) ;
0 commit comments